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