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