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