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