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 }