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 _dscope.d) 9 */ 10 11 module ddmd.dscope; 12 13 import core.stdc.stdio; 14 import core.stdc..string; 15 import ddmd.aggregate; 16 import ddmd.attrib; 17 import ddmd.dclass; 18 import ddmd.declaration; 19 import ddmd.dmodule; 20 import ddmd.doc; 21 import ddmd.dsymbol; 22 import ddmd.dtemplate; 23 import ddmd.errors; 24 import ddmd.func; 25 import ddmd.globals; 26 import ddmd.id; 27 import ddmd.identifier; 28 import ddmd.root.outbuffer; 29 import ddmd.root.rmem; 30 import ddmd.root.speller; 31 import ddmd.statement; 32 33 //version=LOGSEARCH; 34 35 extern (C++) bool mergeFieldInit(Loc loc, ref uint fieldInit, uint fi, bool mustInit) 36 { 37 if (fi != fieldInit) 38 { 39 // Have any branches returned? 40 bool aRet = (fi & CSXreturn) != 0; 41 bool bRet = (fieldInit & CSXreturn) != 0; 42 // Have any branches halted? 43 bool aHalt = (fi & CSXhalt) != 0; 44 bool bHalt = (fieldInit & CSXhalt) != 0; 45 bool ok; 46 if (aHalt && bHalt) 47 { 48 ok = true; 49 fieldInit = CSXhalt; 50 } 51 else if (!aHalt && aRet) 52 { 53 ok = !mustInit || (fi & CSXthis_ctor); 54 fieldInit = fieldInit; 55 } 56 else if (!bHalt && bRet) 57 { 58 ok = !mustInit || (fieldInit & CSXthis_ctor); 59 fieldInit = fi; 60 } 61 else if (aHalt) 62 { 63 ok = !mustInit || (fieldInit & CSXthis_ctor); 64 fieldInit = fieldInit; 65 } 66 else if (bHalt) 67 { 68 ok = !mustInit || (fi & CSXthis_ctor); 69 fieldInit = fi; 70 } 71 else 72 { 73 ok = !mustInit || !((fieldInit ^ fi) & CSXthis_ctor); 74 fieldInit |= fi; 75 } 76 return ok; 77 } 78 return true; 79 } 80 81 enum CSXthis_ctor = 0x01; // called this() 82 enum CSXsuper_ctor = 0x02; // called super() 83 enum CSXthis = 0x04; // referenced this 84 enum CSXsuper = 0x08; // referenced super 85 enum CSXlabel = 0x10; // seen a label 86 enum CSXreturn = 0x20; // seen a return statement 87 enum CSXany_ctor = 0x40; // either this() or super() was called 88 enum CSXhalt = 0x80; // assert(0) 89 90 // Flags that would not be inherited beyond scope nesting 91 enum SCOPEctor = 0x0001; // constructor type 92 enum SCOPEnoaccesscheck = 0x0002; // don't do access checks 93 enum SCOPEcondition = 0x0004; // inside static if/assert condition 94 enum SCOPEdebug = 0x0008; // inside debug conditional 95 96 // Flags that would be inherited beyond scope nesting 97 enum SCOPEconstraint = 0x0010; // inside template constraint 98 enum SCOPEinvariant = 0x0020; // inside invariant code 99 enum SCOPErequire = 0x0040; // inside in contract code 100 enum SCOPEensure = 0x0060; // inside out contract code 101 enum SCOPEcontract = 0x0060; // [mask] we're inside contract code 102 enum SCOPEctfe = 0x0080; // inside a ctfe-only expression 103 enum SCOPEcompile = 0x0100; // inside __traits(compile) 104 enum SCOPEfree = 0x8000; // is on free list 105 106 enum SCOPEfullinst = 0x10000; // fully instantiate templates 107 108 struct Scope 109 { 110 Scope* enclosing; // enclosing Scope 111 112 Module _module; // Root module 113 ScopeDsymbol scopesym; // current symbol 114 ScopeDsymbol sds; // if in static if, and declaring new symbols, 115 // sds gets the addMember() 116 FuncDeclaration func; // function we are in 117 Dsymbol parent; // parent to use 118 LabelStatement slabel; // enclosing labelled statement 119 SwitchStatement sw; // enclosing switch statement 120 TryFinallyStatement tf; // enclosing try finally statement 121 OnScopeStatement os; // enclosing scope(xxx) statement 122 Statement sbreak; // enclosing statement that supports "break" 123 Statement scontinue; // enclosing statement that supports "continue" 124 ForeachStatement fes; // if nested function for ForeachStatement, this is it 125 Scope* callsc; // used for __FUNCTION__, __PRETTY_FUNCTION__ and __MODULE__ 126 int inunion; // we're processing members of a union 127 int nofree; // set if shouldn't free it 128 int noctor; // set if constructor calls aren't allowed 129 int intypeof; // in typeof(exp) 130 VarDeclaration lastVar; // Previous symbol used to prevent goto-skips-init 131 132 /* If minst && !tinst, it's in definitely non-speculative scope (eg. module member scope). 133 * If !minst && !tinst, it's in definitely speculative scope (eg. template constraint). 134 * If minst && tinst, it's in instantiated code scope without speculation. 135 * If !minst && tinst, it's in instantiated code scope with speculation. 136 */ 137 Module minst; // root module where the instantiated templates should belong to 138 TemplateInstance tinst; // enclosing template instance 139 140 // primitive flow analysis for constructors 141 uint callSuper; 142 143 // primitive flow analysis for field initializations 144 uint* fieldinit; 145 size_t fieldinit_dim; 146 147 // alignment for struct members 148 AlignDeclaration aligndecl; 149 150 // linkage for external functions 151 LINK linkage = LINKd; 152 153 // mangle type 154 CPPMANGLE cppmangle = CPPMANGLE.def; 155 156 // inlining strategy for functions 157 PINLINE inlining = PINLINEdefault; 158 159 // protection for class members 160 Prot protection = Prot(PROTpublic); 161 int explicitProtection; // set if in an explicit protection attribute 162 163 StorageClass stc; // storage class 164 165 DeprecatedDeclaration depdecl; // customized deprecation message 166 167 uint flags; 168 169 // user defined attributes 170 UserAttributeDeclaration userAttribDecl; 171 172 DocComment* lastdc; // documentation comment for last symbol at this scope 173 uint[void*] anchorCounts; // lookup duplicate anchor name count 174 Identifier prevAnchor; // qualified symbol name of last doc anchor 175 176 extern (C++) static __gshared Scope* freelist; 177 178 extern (C++) static Scope* alloc() 179 { 180 if (freelist) 181 { 182 Scope* s = freelist; 183 freelist = s.enclosing; 184 //printf("freelist %p\n", s); 185 assert(s.flags & SCOPEfree); 186 s.flags &= ~SCOPEfree; 187 return s; 188 } 189 return new Scope(); 190 } 191 192 extern (C++) static Scope* createGlobal(Module _module) 193 { 194 Scope* sc = Scope.alloc(); 195 *sc = Scope.init; 196 sc._module = _module; 197 sc.minst = _module; 198 sc.scopesym = new ScopeDsymbol(); 199 sc.scopesym.symtab = new DsymbolTable(); 200 // Add top level package as member of this global scope 201 Dsymbol m = _module; 202 while (m.parent) 203 m = m.parent; 204 m.addMember(null, sc.scopesym); 205 m.parent = null; // got changed by addMember() 206 // Create the module scope underneath the global scope 207 sc = sc.push(_module); 208 sc.parent = _module; 209 return sc; 210 } 211 212 extern (C++) Scope* copy() 213 { 214 Scope* sc = Scope.alloc(); 215 *sc = this; 216 /* Bugzilla 11777: The copied scope should not inherit fieldinit. 217 */ 218 sc.fieldinit = null; 219 return sc; 220 } 221 222 extern (C++) Scope* push() 223 { 224 Scope* s = copy(); 225 //printf("Scope::push(this = %p) new = %p\n", this, s); 226 assert(!(flags & SCOPEfree)); 227 s.scopesym = null; 228 s.sds = null; 229 s.enclosing = &this; 230 debug 231 { 232 if (enclosing) 233 assert(!(enclosing.flags & SCOPEfree)); 234 if (s == enclosing) 235 { 236 printf("this = %p, enclosing = %p, enclosing->enclosing = %p\n", s, &this, enclosing); 237 } 238 assert(s != enclosing); 239 } 240 s.slabel = null; 241 s.nofree = 0; 242 s.fieldinit = saveFieldInit(); 243 s.flags = (flags & (SCOPEcontract | SCOPEdebug | SCOPEctfe | SCOPEcompile | SCOPEconstraint)); 244 s.lastdc = null; 245 assert(&this != s); 246 return s; 247 } 248 249 extern (C++) Scope* push(ScopeDsymbol ss) 250 { 251 //printf("Scope::push(%s)\n", ss->toChars()); 252 Scope* s = push(); 253 s.scopesym = ss; 254 return s; 255 } 256 257 extern (C++) Scope* pop() 258 { 259 //printf("Scope::pop() %p nofree = %d\n", this, nofree); 260 Scope* enc = enclosing; 261 if (enclosing) 262 { 263 enclosing.callSuper |= callSuper; 264 if (fieldinit) 265 { 266 if (enclosing.fieldinit) 267 { 268 assert(fieldinit != enclosing.fieldinit); 269 foreach (i; 0 .. fieldinit_dim) 270 enclosing.fieldinit[i] |= fieldinit[i]; 271 } 272 freeFieldinit(); 273 } 274 } 275 if (!nofree) 276 { 277 enclosing = freelist; 278 freelist = &this; 279 flags |= SCOPEfree; 280 } 281 return enc; 282 } 283 284 void allocFieldinit(size_t dim) 285 { 286 fieldinit = cast(typeof(fieldinit))mem.xcalloc(typeof(*fieldinit).sizeof, dim); 287 fieldinit_dim = dim; 288 } 289 290 void freeFieldinit() 291 { 292 if (fieldinit) 293 mem.xfree(fieldinit); 294 fieldinit = null; 295 fieldinit_dim = 0; 296 } 297 298 extern (C++) Scope* startCTFE() 299 { 300 Scope* sc = this.push(); 301 sc.flags = this.flags | SCOPEctfe; 302 version (none) 303 { 304 /* TODO: Currently this is not possible, because we need to 305 * unspeculative some types and symbols if they are necessary for the 306 * final executable. Consider: 307 * 308 * struct S(T) { 309 * string toString() const { return "instantiated"; } 310 * } 311 * enum x = S!int(); 312 * void main() { 313 * // To call x.toString in runtime, compiler should unspeculative S!int. 314 * assert(x.toString() == "instantiated"); 315 * } 316 */ 317 // If a template is instantiated from CT evaluated expression, 318 // compiler can elide its code generation. 319 sc.tinst = null; 320 sc.minst = null; 321 } 322 return sc; 323 } 324 325 extern (C++) Scope* endCTFE() 326 { 327 assert(flags & SCOPEctfe); 328 return pop(); 329 } 330 331 extern (C++) void mergeCallSuper(Loc loc, uint cs) 332 { 333 // This does a primitive flow analysis to support the restrictions 334 // regarding when and how constructors can appear. 335 // It merges the results of two paths. 336 // The two paths are callSuper and cs; the result is merged into callSuper. 337 if (cs != callSuper) 338 { 339 // Have ALL branches called a constructor? 340 int aAll = (cs & (CSXthis_ctor | CSXsuper_ctor)) != 0; 341 int bAll = (callSuper & (CSXthis_ctor | CSXsuper_ctor)) != 0; 342 // Have ANY branches called a constructor? 343 bool aAny = (cs & CSXany_ctor) != 0; 344 bool bAny = (callSuper & CSXany_ctor) != 0; 345 // Have any branches returned? 346 bool aRet = (cs & CSXreturn) != 0; 347 bool bRet = (callSuper & CSXreturn) != 0; 348 // Have any branches halted? 349 bool aHalt = (cs & CSXhalt) != 0; 350 bool bHalt = (callSuper & CSXhalt) != 0; 351 bool ok = true; 352 if (aHalt && bHalt) 353 { 354 callSuper = CSXhalt; 355 } 356 else if ((!aHalt && aRet && !aAny && bAny) || (!bHalt && bRet && !bAny && aAny)) 357 { 358 // If one has returned without a constructor call, there must be never 359 // have been ctor calls in the other. 360 ok = false; 361 } 362 else if (aHalt || aRet && aAll) 363 { 364 // If one branch has called a ctor and then exited, anything the 365 // other branch has done is OK (except returning without a 366 // ctor call, but we already checked that). 367 callSuper |= cs & (CSXany_ctor | CSXlabel); 368 } 369 else if (bHalt || bRet && bAll) 370 { 371 callSuper = cs | (callSuper & (CSXany_ctor | CSXlabel)); 372 } 373 else 374 { 375 // Both branches must have called ctors, or both not. 376 ok = (aAll == bAll); 377 // If one returned without a ctor, we must remember that 378 // (Don't bother if we've already found an error) 379 if (ok && aRet && !aAny) 380 callSuper |= CSXreturn; 381 callSuper |= cs & (CSXany_ctor | CSXlabel); 382 } 383 if (!ok) 384 error(loc, "one path skips constructor"); 385 } 386 } 387 388 extern (C++) uint* saveFieldInit() 389 { 390 uint* fi = null; 391 if (fieldinit) // copy 392 { 393 size_t dim = fieldinit_dim; 394 fi = cast(uint*)mem.xmalloc(uint.sizeof * dim); 395 for (size_t i = 0; i < dim; i++) 396 fi[i] = fieldinit[i]; 397 } 398 return fi; 399 } 400 401 extern (C++) void mergeFieldInit(Loc loc, uint* fies) 402 { 403 if (fieldinit && fies) 404 { 405 FuncDeclaration f = func; 406 if (fes) 407 f = fes.func; 408 auto ad = f.isMember2(); 409 assert(ad); 410 for (size_t i = 0; i < ad.fields.dim; i++) 411 { 412 VarDeclaration v = ad.fields[i]; 413 bool mustInit = (v.storage_class & STCnodefaultctor || v.type.needsNested()); 414 if (!.mergeFieldInit(loc, fieldinit[i], fies[i], mustInit)) 415 { 416 .error(loc, "one path skips field %s", ad.fields[i].toChars()); 417 } 418 } 419 } 420 } 421 422 extern (C++) Module instantiatingModule() 423 { 424 // TODO: in speculative context, returning 'module' is correct? 425 return minst ? minst : _module; 426 } 427 428 /************************************ 429 * Perform unqualified name lookup by following the chain of scopes up 430 * until found. 431 * 432 * Params: 433 * loc = location to use for error messages 434 * ident = name to look up 435 * pscopesym = if supplied and name is found, set to scope that ident was found in 436 * flags = modify search based on flags 437 * 438 * Returns: 439 * symbol if found, null if not 440 */ 441 extern (C++) Dsymbol search(Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone) 442 { 443 version (LOGSEARCH) 444 { 445 printf("Scope.search(%p, '%s' flags=x%x)\n", &this, ident.toChars(), flags); 446 // Print scope chain 447 for (Scope* sc = &this; sc; sc = sc.enclosing) 448 { 449 if (!sc.scopesym) 450 continue; 451 printf("\tscope %s\n", sc.scopesym.toChars()); 452 } 453 454 static void printMsg(string txt, Dsymbol s) 455 { 456 printf("%.*s %s.%s, kind = '%s'\n", cast(int)msg.length, msg.ptr, 457 s.parent ? s.parent.toChars() : "", s.toChars(), s.kind()); 458 } 459 } 460 461 // This function is called only for unqualified lookup 462 assert(!(flags & (SearchLocalsOnly | SearchImportsOnly))); 463 464 /* If ident is "start at module scope", only look at module scope 465 */ 466 if (ident == Id.empty) 467 { 468 // Look for module scope 469 for (Scope* sc = &this; sc; sc = sc.enclosing) 470 { 471 assert(sc != sc.enclosing); 472 if (!sc.scopesym) 473 continue; 474 if (Dsymbol s = sc.scopesym.isModule()) 475 { 476 //printMsg("\tfound", s); 477 if (pscopesym) 478 *pscopesym = sc.scopesym; 479 return s; 480 } 481 } 482 return null; 483 } 484 485 Dsymbol searchScopes(int flags) 486 { 487 for (Scope* sc = &this; sc; sc = sc.enclosing) 488 { 489 assert(sc != sc.enclosing); 490 if (!sc.scopesym) 491 continue; 492 //printf("\tlooking in scopesym '%s', kind = '%s', flags = x%x\n", sc.scopesym.toChars(), sc.scopesym.kind(), flags); 493 494 if (sc.scopesym.isModule()) 495 flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed 496 497 if (Dsymbol s = sc.scopesym.search(loc, ident, flags)) 498 { 499 if (!(flags & (SearchImportsOnly | IgnoreErrors)) && 500 ident == Id.length && sc.scopesym.isArrayScopeSymbol() && 501 sc.enclosing && sc.enclosing.search(loc, ident, null, flags)) 502 { 503 warning(s.loc, "array 'length' hides other 'length' name in outer scope"); 504 } 505 //printMsg("\tfound local", s); 506 if (pscopesym) 507 *pscopesym = sc.scopesym; 508 return s; 509 } 510 // Stop when we hit a module, but keep going if that is not just under the global scope 511 if (sc.scopesym.isModule() && !(sc.enclosing && !sc.enclosing.enclosing)) 512 break; 513 } 514 return null; 515 } 516 517 Dsymbol sold = void; 518 if (global.params.bug10378 || global.params.check10378) 519 { 520 sold = searchScopes(flags | IgnoreSymbolVisibility); 521 if (!global.params.check10378) 522 return sold; 523 524 if (ident == Id.dollar) // Bugzilla 15825 525 return sold; 526 527 // Search both ways 528 } 529 530 // First look in local scopes 531 Dsymbol s = searchScopes(flags | SearchLocalsOnly); 532 version (LOGSEARCH) if (s) printMsg("-Scope.search() found local", s); 533 if (!s) 534 { 535 // Second look in imported modules 536 s = searchScopes(flags | SearchImportsOnly); 537 version (LOGSEARCH) if (s) printMsg("-Scope.search() found import", s); 538 539 /** Still find private symbols, so that symbols that weren't access 540 * checked by the compiler remain usable. Once the deprecation is over, 541 * this should be moved to search_correct instead. 542 */ 543 if (!s) 544 { 545 s = searchScopes(flags | SearchLocalsOnly | IgnoreSymbolVisibility); 546 if (!s) 547 s = searchScopes(flags | SearchImportsOnly | IgnoreSymbolVisibility); 548 549 if (s && !(flags & IgnoreErrors)) 550 .deprecation(loc, "%s is not visible from module %s", s.toPrettyChars(), _module.toChars()); 551 version (LOGSEARCH) if (s) printMsg("-Scope.search() found imported private symbol", s); 552 } 553 } 554 if (global.params.check10378) 555 { 556 alias snew = s; 557 if (sold !is snew) 558 deprecation10378(loc, sold, snew); 559 if (global.params.bug10378) 560 s = sold; 561 } 562 return s; 563 } 564 565 /* A helper function to show deprecation message for new name lookup rule. 566 */ 567 extern (C++) static void deprecation10378(Loc loc, Dsymbol sold, Dsymbol snew) 568 { 569 OutBuffer buf; 570 buf.writestring("local import search method found "); 571 if (sold) 572 buf.printf("%s %s", sold.kind(), sold.toPrettyChars()); 573 else 574 buf.writestring("nothing"); 575 buf.writestring(" instead of "); 576 if (snew) 577 buf.printf("%s %s", snew.kind(), snew.toPrettyChars()); 578 else 579 buf.writestring("nothing"); 580 581 deprecation(loc, buf.peekString()); 582 } 583 584 extern (C++) Dsymbol search_correct(Identifier ident) 585 { 586 if (global.gag) 587 return null; // don't do it for speculative compiles; too time consuming 588 589 /************************************************ 590 * Given the failed search attempt, try to find 591 * one with a close spelling. 592 */ 593 extern (D) void* scope_search_fp(const(char)* seed, ref int cost) 594 { 595 //printf("scope_search_fp('%s')\n", seed); 596 /* If not in the lexer's string table, it certainly isn't in the symbol table. 597 * Doing this first is a lot faster. 598 */ 599 size_t len = strlen(seed); 600 if (!len) 601 return null; 602 Identifier id = Identifier.lookup(seed, len); 603 if (!id) 604 return null; 605 Scope* sc = &this; 606 Module.clearCache(); 607 Dsymbol scopesym = null; 608 Dsymbol s = sc.search(Loc(), id, &scopesym, IgnoreErrors); 609 if (s) 610 { 611 for (cost = 0; sc; sc = sc.enclosing, ++cost) 612 if (sc.scopesym == scopesym) 613 break; 614 if (scopesym != s.parent) 615 { 616 ++cost; // got to the symbol through an import 617 if (s.prot().kind == PROTprivate) 618 return null; 619 } 620 } 621 return cast(void*)s; 622 } 623 624 return cast(Dsymbol)speller(ident.toChars(), &scope_search_fp, idchars); 625 } 626 627 extern (C++) Dsymbol insert(Dsymbol s) 628 { 629 if (VarDeclaration vd = s.isVarDeclaration()) 630 { 631 if (lastVar) 632 vd.lastVar = lastVar; 633 lastVar = vd; 634 } 635 else if (WithScopeSymbol ss = s.isWithScopeSymbol()) 636 { 637 if (VarDeclaration vd = ss.withstate.wthis) 638 { 639 if (lastVar) 640 vd.lastVar = lastVar; 641 lastVar = vd; 642 } 643 return null; 644 } 645 for (Scope* sc = &this; sc; sc = sc.enclosing) 646 { 647 //printf("\tsc = %p\n", sc); 648 if (sc.scopesym) 649 { 650 //printf("\t\tsc->scopesym = %p\n", sc->scopesym); 651 if (!sc.scopesym.symtab) 652 sc.scopesym.symtab = new DsymbolTable(); 653 return sc.scopesym.symtabInsert(s); 654 } 655 } 656 assert(0); 657 } 658 659 /******************************************** 660 * Search enclosing scopes for ClassDeclaration. 661 */ 662 extern (C++) ClassDeclaration getClassScope() 663 { 664 for (Scope* sc = &this; sc; sc = sc.enclosing) 665 { 666 if (!sc.scopesym) 667 continue; 668 ClassDeclaration cd = sc.scopesym.isClassDeclaration(); 669 if (cd) 670 return cd; 671 } 672 return null; 673 } 674 675 /******************************************** 676 * Search enclosing scopes for ClassDeclaration. 677 */ 678 extern (C++) AggregateDeclaration getStructClassScope() 679 { 680 for (Scope* sc = &this; sc; sc = sc.enclosing) 681 { 682 if (!sc.scopesym) 683 continue; 684 AggregateDeclaration ad = sc.scopesym.isClassDeclaration(); 685 if (ad) 686 return ad; 687 ad = sc.scopesym.isStructDeclaration(); 688 if (ad) 689 return ad; 690 } 691 return null; 692 } 693 694 /******************************************* 695 * For TemplateDeclarations, we need to remember the Scope 696 * where it was declared. So mark the Scope as not 697 * to be free'd. 698 */ 699 extern (C++) void setNoFree() 700 { 701 //int i = 0; 702 //printf("Scope::setNoFree(this = %p)\n", this); 703 for (Scope* sc = &this; sc; sc = sc.enclosing) 704 { 705 //printf("\tsc = %p\n", sc); 706 sc.nofree = 1; 707 assert(!(flags & SCOPEfree)); 708 //assert(sc != sc->enclosing); 709 //assert(!sc->enclosing || sc != sc->enclosing->enclosing); 710 //if (++i == 10) 711 // assert(0); 712 } 713 } 714 715 extern (D) this(ref Scope sc) 716 { 717 this._module = sc._module; 718 this.scopesym = sc.scopesym; 719 this.sds = sc.sds; 720 this.enclosing = sc.enclosing; 721 this.parent = sc.parent; 722 this.sw = sc.sw; 723 this.tf = sc.tf; 724 this.os = sc.os; 725 this.tinst = sc.tinst; 726 this.minst = sc.minst; 727 this.sbreak = sc.sbreak; 728 this.scontinue = sc.scontinue; 729 this.fes = sc.fes; 730 this.callsc = sc.callsc; 731 this.aligndecl = sc.aligndecl; 732 this.func = sc.func; 733 this.slabel = sc.slabel; 734 this.linkage = sc.linkage; 735 this.cppmangle = sc.cppmangle; 736 this.inlining = sc.inlining; 737 this.protection = sc.protection; 738 this.explicitProtection = sc.explicitProtection; 739 this.stc = sc.stc; 740 this.depdecl = sc.depdecl; 741 this.inunion = sc.inunion; 742 this.nofree = sc.nofree; 743 this.noctor = sc.noctor; 744 this.intypeof = sc.intypeof; 745 this.lastVar = sc.lastVar; 746 this.callSuper = sc.callSuper; 747 this.fieldinit = sc.fieldinit; 748 this.fieldinit_dim = sc.fieldinit_dim; 749 this.flags = sc.flags; 750 this.lastdc = sc.lastdc; 751 this.anchorCounts = sc.anchorCounts; 752 this.prevAnchor = sc.prevAnchor; 753 this.userAttribDecl = sc.userAttribDecl; 754 } 755 756 structalign_t alignment() 757 { 758 if (aligndecl) 759 return aligndecl.getAlignment(); 760 else 761 return STRUCTALIGN_DEFAULT; 762 } 763 }