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 }