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