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