1 /**
2  * Defines AST nodes for the parsing stage.
3  *
4  * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
5  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
6  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/astbase.d, _astbase.d)
7  * Documentation:  https://dlang.org/phobos/dmd_astbase.html
8  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/astbase.d
9  */
10 
11 module dmd.astbase;
12 
13 import dmd.parsetimevisitor;
14 
15 /** The ASTBase  family defines a family of AST nodes appropriate for parsing with
16   * no semantic information. It defines all the AST nodes that the parser needs
17   * and also all the conveniance methods and variables. The resulting AST can be
18   * visited with the strict, permissive and transitive visitors.
19   * The ASTBase family is used to instantiate the parser in the parser library.
20   */
21 struct ASTBase
22 {
23     import dmd.root.file;
24     import dmd.root.filename;
25     import dmd.root.array;
26     import dmd.root.rootobject;
27     import dmd.root.outbuffer;
28     import dmd.root.ctfloat;
29     import dmd.root.rmem;
30     import dmd.root.string : toDString;
31     import dmd.root.stringtable;
32 
33     import dmd.tokens;
34     import dmd.identifier;
35     import dmd.globals;
36     import dmd.id;
37     import dmd.errors;
38     import dmd.lexer;
39 
40     import core.stdc.string;
41     import core.stdc.stdarg;
42 
43     alias Dsymbols              = Array!(Dsymbol);
44     alias Objects               = Array!(RootObject);
45     alias Expressions           = Array!(Expression);
46     alias TemplateParameters    = Array!(TemplateParameter);
47     alias BaseClasses           = Array!(BaseClass*);
48     alias Parameters            = Array!(Parameter);
49     alias Statements            = Array!(Statement);
50     alias Catches               = Array!(Catch);
51     alias Identifiers           = Array!(Identifier);
52     alias Initializers          = Array!(Initializer);
53     alias Ensures               = Array!(Ensure);
54 
55     enum Sizeok : int
56     {
57         none,               // size of aggregate is not yet able to compute
58         fwd,                // size of aggregate is ready to compute
59         done,               // size of aggregate is set correctly
60     }
61 
62     enum Baseok : int
63     {
64         none,               // base classes not computed yet
65         start,              // in process of resolving base classes
66         done,               // all base classes are resolved
67         semanticdone,       // all base classes semantic done
68     }
69 
70     enum MODFlags : int
71     {
72         const_       = 1,    // type is const
73         immutable_   = 4,    // type is immutable
74         shared_      = 2,    // type is shared
75         wild         = 8,    // type is wild
76         wildconst    = (MODFlags.wild | MODFlags.const_), // type is wild const
77         mutable      = 0x10, // type is mutable (only used in wildcard matching)
78     }
79 
80     alias MOD = ubyte;
81 
82     enum STC : ulong
83     {
84         undefined_          = 0L,
85         static_             = (1L << 0),
86         extern_             = (1L << 1),
87         const_              = (1L << 2),
88         final_              = (1L << 3),
89         abstract_           = (1L << 4),
90         parameter           = (1L << 5),
91         field               = (1L << 6),
92         override_           = (1L << 7),
93         auto_               = (1L << 8),
94         synchronized_       = (1L << 9),
95         deprecated_         = (1L << 10),
96         in_                 = (1L << 11),   // in parameter
97         out_                = (1L << 12),   // out parameter
98         lazy_               = (1L << 13),   // lazy parameter
99         foreach_            = (1L << 14),   // variable for foreach loop
100                               //(1L << 15)
101         variadic            = (1L << 16),   // the 'variadic' parameter in: T foo(T a, U b, V variadic...)
102         ctorinit            = (1L << 17),   // can only be set inside constructor
103         templateparameter   = (1L << 18),   // template parameter
104         scope_              = (1L << 19),
105         immutable_          = (1L << 20),
106         ref_                = (1L << 21),
107         init                = (1L << 22),   // has explicit initializer
108         manifest            = (1L << 23),   // manifest constant
109         nodtor              = (1L << 24),   // don't run destructor
110         nothrow_            = (1L << 25),   // never throws exceptions
111         pure_               = (1L << 26),   // pure function
112         tls                 = (1L << 27),   // thread local
113         alias_              = (1L << 28),   // alias parameter
114         shared_             = (1L << 29),   // accessible from multiple threads
115         gshared             = (1L << 30),   // accessible from multiple threads, but not typed as "shared"
116         wild                = (1L << 31),   // for "wild" type constructor
117         property            = (1L << 32),
118         safe                = (1L << 33),
119         trusted             = (1L << 34),
120         system              = (1L << 35),
121         ctfe                = (1L << 36),   // can be used in CTFE, even if it is static
122         disable             = (1L << 37),   // for functions that are not callable
123         result              = (1L << 38),   // for result variables passed to out contracts
124         nodefaultctor       = (1L << 39),   // must be set inside constructor
125         temp                = (1L << 40),   // temporary variable
126         rvalue              = (1L << 41),   // force rvalue for variables
127         nogc                = (1L << 42),   // @nogc
128         volatile_           = (1L << 43),   // destined for volatile in the back end
129         return_             = (1L << 44),   // 'return ref' or 'return scope' for function parameters
130         autoref             = (1L << 45),   // Mark for the already deduced 'auto ref' parameter
131         inference           = (1L << 46),   // do attribute inference
132         exptemp             = (1L << 47),   // temporary variable that has lifetime restricted to an expression
133         maybescope          = (1L << 48),   // parameter might be 'scope'
134         scopeinferred       = (1L << 49),   // 'scope' has been inferred and should not be part of mangling
135         future              = (1L << 50),   // introducing new base class function
136         local               = (1L << 51),   // do not forward (see dmd.dsymbol.ForwardingScopeDsymbol).
137         returninferred      = (1L << 52),   // 'return' has been inferred and should not be part of mangling
138         live                = (1L << 53),   // function @live attribute
139 
140         safeGroup = STC.safe | STC.trusted | STC.system,
141         IOR  = STC.in_ | STC.ref_ | STC.out_,
142         TYPECTOR = (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild),
143         FUNCATTR = (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.property | STC.live |
144                     safeGroup),
145     }
146 
147     extern (C++) __gshared const(StorageClass) STCStorageClass =
148         (STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.const_ | STC.final_ |
149          STC.abstract_ | STC.synchronized_ | STC.deprecated_ | STC.override_ | STC.lazy_ |
150          STC.alias_ | STC.out_ | STC.in_ | STC.manifest | STC.immutable_ | STC.shared_ |
151          STC.wild | STC.nothrow_ | STC.nogc | STC.pure_ | STC.ref_ | STC.return_ | STC.tls |
152          STC.gshared | STC.property | STC.live |
153          STC.safeGroup | STC.disable);
154 
155     enum ENUMTY : int
156     {
157         Tarray,     // slice array, aka T[]
158         Tsarray,    // static array, aka T[dimension]
159         Taarray,    // associative array, aka T[type]
160         Tpointer,
161         Treference,
162         Tfunction,
163         Tident,
164         Tclass,
165         Tstruct,
166         Tenum,
167 
168         Tdelegate,
169         Tnone,
170         Tvoid,
171         Tint8,
172         Tuns8,
173         Tint16,
174         Tuns16,
175         Tint32,
176         Tuns32,
177         Tint64,
178 
179         Tuns64,
180         Tfloat32,
181         Tfloat64,
182         Tfloat80,
183         Timaginary32,
184         Timaginary64,
185         Timaginary80,
186         Tcomplex32,
187         Tcomplex64,
188         Tcomplex80,
189 
190         Tbool,
191         Tchar,
192         Twchar,
193         Tdchar,
194         Terror,
195         Tinstance,
196         Ttypeof,
197         Ttuple,
198         Tslice,
199         Treturn,
200 
201         Tnull,
202         Tvector,
203         Tint128,
204         Tuns128,
205         Ttraits,
206         Tmixin,
207         TMAX
208     }
209 
210     alias Tarray = ENUMTY.Tarray;
211     alias Tsarray = ENUMTY.Tsarray;
212     alias Taarray = ENUMTY.Taarray;
213     alias Tpointer = ENUMTY.Tpointer;
214     alias Treference = ENUMTY.Treference;
215     alias Tfunction = ENUMTY.Tfunction;
216     alias Tident = ENUMTY.Tident;
217     alias Tclass = ENUMTY.Tclass;
218     alias Tstruct = ENUMTY.Tstruct;
219     alias Tenum = ENUMTY.Tenum;
220     alias Tdelegate = ENUMTY.Tdelegate;
221     alias Tnone = ENUMTY.Tnone;
222     alias Tvoid = ENUMTY.Tvoid;
223     alias Tint8 = ENUMTY.Tint8;
224     alias Tuns8 = ENUMTY.Tuns8;
225     alias Tint16 = ENUMTY.Tint16;
226     alias Tuns16 = ENUMTY.Tuns16;
227     alias Tint32 = ENUMTY.Tint32;
228     alias Tuns32 = ENUMTY.Tuns32;
229     alias Tint64 = ENUMTY.Tint64;
230     alias Tuns64 = ENUMTY.Tuns64;
231     alias Tfloat32 = ENUMTY.Tfloat32;
232     alias Tfloat64 = ENUMTY.Tfloat64;
233     alias Tfloat80 = ENUMTY.Tfloat80;
234     alias Timaginary32 = ENUMTY.Timaginary32;
235     alias Timaginary64 = ENUMTY.Timaginary64;
236     alias Timaginary80 = ENUMTY.Timaginary80;
237     alias Tcomplex32 = ENUMTY.Tcomplex32;
238     alias Tcomplex64 = ENUMTY.Tcomplex64;
239     alias Tcomplex80 = ENUMTY.Tcomplex80;
240     alias Tbool = ENUMTY.Tbool;
241     alias Tchar = ENUMTY.Tchar;
242     alias Twchar = ENUMTY.Twchar;
243     alias Tdchar = ENUMTY.Tdchar;
244     alias Terror = ENUMTY.Terror;
245     alias Tinstance = ENUMTY.Tinstance;
246     alias Ttypeof = ENUMTY.Ttypeof;
247     alias Ttuple = ENUMTY.Ttuple;
248     alias Tslice = ENUMTY.Tslice;
249     alias Treturn = ENUMTY.Treturn;
250     alias Tnull = ENUMTY.Tnull;
251     alias Tvector = ENUMTY.Tvector;
252     alias Tint128 = ENUMTY.Tint128;
253     alias Tuns128 = ENUMTY.Tuns128;
254     alias Ttraits = ENUMTY.Ttraits;
255     alias Tmixin = ENUMTY.Tmixin;
256     alias TMAX = ENUMTY.TMAX;
257 
258     alias TY = ubyte;
259 
260     enum TFlags
261     {
262         integral     = 1,
263         floating     = 2,
264         unsigned     = 4,
265         real_        = 8,
266         imaginary    = 0x10,
267         complex      = 0x20,
268     }
269 
270     enum PKG : int
271     {
272         unknown,     // not yet determined whether it's a package.d or not
273         module_,      // already determined that's an actual package.d
274         package_,     // already determined that's an actual package
275     }
276 
277     enum StructPOD : int
278     {
279         no,    // struct is not POD
280         yes,   // struct is POD
281         fwd,   // POD not yet computed
282     }
283 
284     enum TRUST : ubyte
285     {
286         default_   = 0,
287         system     = 1,    // @system (same as TRUST.default)
288         trusted    = 2,    // @trusted
289         safe       = 3,    // @safe
290         live       = 4,    // @live
291     }
292 
293     enum PURE : ubyte
294     {
295         impure      = 0,    // not pure at all
296         fwdref      = 1,    // it's pure, but not known which level yet
297         weak        = 2,    // no mutable globals are read or written
298         const_      = 3,    // parameters are values or const
299         strong      = 4,    // parameters are values or immutable
300     }
301 
302     enum AliasThisRec : int
303     {
304         no           = 0,    // no alias this recursion
305         yes          = 1,    // alias this has recursive dependency
306         fwdref       = 2,    // not yet known
307         typeMask     = 3,    // mask to read no/yes/fwdref
308         tracing      = 0x4,  // mark in progress of implicitConvTo/deduceWild
309         tracingDT    = 0x8,  // mark in progress of deduceType
310     }
311 
312     enum VarArg : ubyte
313     {
314         none     = 0,  /// fixed number of arguments
315         variadic = 1,  /// T t, ...)  can be C-style (core.stdc.stdarg) or D-style (core.vararg)
316         typesafe = 2,  /// T t ...) typesafe https://dlang.org/spec/function.html#typesafe_variadic_functions
317                        ///   or https://dlang.org/spec/function.html#typesafe_variadic_functions
318     }
319 
320     alias Visitor = ParseTimeVisitor!ASTBase;
321 
322     extern (C++) abstract class ASTNode : RootObject
323     {
324         abstract void accept(Visitor v);
325     }
326 
327     extern (C++) class Dsymbol : ASTNode
328     {
329         Loc loc;
330         Identifier ident;
331         UnitTestDeclaration ddocUnittest;
332         UserAttributeDeclaration userAttribDecl;
333         Dsymbol parent;
334 
335         const(char)* comment;
336 
337         final extern (D) this() {}
338         final extern (D) this(Identifier ident)
339         {
340             this.ident = ident;
341         }
342 
343         void addComment(const(char)* comment)
344         {
345             if (!this.comment)
346                 this.comment = comment;
347             else if (comment && strcmp(cast(char*)comment, cast(char*)this.comment) != 0)
348                 this.comment = Lexer.combineComments(this.comment.toDString(), comment.toDString(), true);
349         }
350 
351         override const(char)* toChars() const
352         {
353             return ident ? ident.toChars() : "__anonymous";
354         }
355 
356         bool oneMember(Dsymbol *ps, Identifier ident)
357         {
358             *ps = this;
359             return true;
360         }
361 
362         extern (D) static bool oneMembers(ref Dsymbols members, Dsymbol* ps, Identifier ident)
363         {
364             Dsymbol s = null;
365             for (size_t i = 0; i < members.dim; i++)
366             {
367                 Dsymbol sx = members[i];
368                 bool x = sx.oneMember(ps, ident);
369                 if (!x)
370                 {
371                     assert(*ps is null);
372                     return false;
373                 }
374                 if (*ps)
375                 {
376                     assert(ident);
377                     if (!(*ps).ident || !(*ps).ident.equals(ident))
378                         continue;
379                     if (!s)
380                         s = *ps;
381                     else if (s.isOverloadable() && (*ps).isOverloadable())
382                     {
383                         // keep head of overload set
384                         FuncDeclaration f1 = s.isFuncDeclaration();
385                         FuncDeclaration f2 = (*ps).isFuncDeclaration();
386                         if (f1 && f2)
387                         {
388                             for (; f1 != f2; f1 = f1.overnext0)
389                             {
390                                 if (f1.overnext0 is null)
391                                 {
392                                     f1.overnext0 = f2;
393                                     break;
394                                 }
395                             }
396                         }
397                     }
398                     else // more than one symbol
399                     {
400                         *ps = null;
401                         //printf("\tfalse 2\n");
402                         return false;
403                     }
404                 }
405             }
406             *ps = s;
407             return true;
408         }
409 
410         bool isOverloadable() const
411         {
412             return false;
413         }
414 
415         const(char)* kind() const
416         {
417             return "symbol";
418         }
419 
420         static if (__VERSION__ < 2092)
421             final void error(const(char)* format, ...)
422             {
423                 va_list ap;
424                 va_start(ap, format);
425                 // last parameter : toPrettyChars
426                 verror(loc, format, ap, kind(), "");
427                 va_end(ap);
428             }
429         else
430             pragma(printf) final void error(const(char)* format, ...)
431             {
432                 va_list ap;
433                 va_start(ap, format);
434                 // last parameter : toPrettyChars
435                 verror(loc, format, ap, kind(), "");
436                 va_end(ap);
437             }
438 
439         inout(AttribDeclaration) isAttribDeclaration() inout
440         {
441             return null;
442         }
443 
444         inout(TemplateDeclaration) isTemplateDeclaration() inout
445         {
446             return null;
447         }
448 
449         inout(FuncLiteralDeclaration) isFuncLiteralDeclaration() inout
450         {
451             return null;
452         }
453 
454         inout(FuncDeclaration) isFuncDeclaration() inout
455         {
456             return null;
457         }
458 
459         inout(VarDeclaration) isVarDeclaration() inout
460         {
461             return null;
462         }
463 
464         inout(TemplateInstance) isTemplateInstance() inout
465         {
466             return null;
467         }
468 
469         inout(Declaration) isDeclaration() inout
470         {
471             return null;
472         }
473 
474         inout(ClassDeclaration) isClassDeclaration() inout
475         {
476             return null;
477         }
478 
479         inout(AggregateDeclaration) isAggregateDeclaration() inout
480         {
481             return null;
482         }
483 
484         Dsymbol syntaxCopy(Dsymbol s)
485         {
486             return null;
487         }
488 
489         override final DYNCAST dyncast() const
490         {
491             return DYNCAST.dsymbol;
492         }
493 
494         override void accept(Visitor v)
495         {
496             v.visit(this);
497         }
498     }
499 
500     extern (C++) class AliasThis : Dsymbol
501     {
502         Identifier ident;
503 
504         extern (D) this(const ref Loc loc, Identifier ident)
505         {
506             super(null);
507             this.loc = loc;
508             this.ident = ident;
509         }
510 
511         override void accept(Visitor v)
512         {
513             v.visit(this);
514         }
515     }
516 
517     extern (C++) abstract class Declaration : Dsymbol
518     {
519         StorageClass storage_class;
520         Prot protection;
521         LINK linkage;
522         Type type;
523 
524         final extern (D) this(Identifier id)
525         {
526             super(id);
527             storage_class = STC.undefined_;
528             protection = Prot(Prot.Kind.undefined);
529             linkage = LINK.default_;
530         }
531 
532         override final inout(Declaration) isDeclaration() inout
533         {
534             return this;
535         }
536 
537         override void accept(Visitor v)
538         {
539             v.visit(this);
540         }
541     }
542 
543     extern (C++) class ScopeDsymbol : Dsymbol
544     {
545         Dsymbols* members;
546         final extern (D) this() {}
547         final extern (D) this(Identifier id)
548         {
549             super(id);
550         }
551 
552         override void accept(Visitor v)
553         {
554             v.visit(this);
555         }
556     }
557 
558     extern (C++) class Import : Dsymbol
559     {
560         Identifiers* packages;
561         Identifier id;
562         Identifier aliasId;
563         int isstatic;
564         Prot protection;
565 
566         Identifiers names;
567         Identifiers aliases;
568 
569         extern (D) this(const ref Loc loc, Identifiers* packages, Identifier id, Identifier aliasId, int isstatic)
570         {
571             super(null);
572             this.loc = loc;
573             this.packages = packages;
574             this.id = id;
575             this.aliasId = aliasId;
576             this.isstatic = isstatic;
577             this.protection = Prot(Prot.Kind.private_);
578 
579             if (aliasId)
580             {
581                 // import [cstdio] = std.stdio;
582                 this.ident = aliasId;
583             }
584             else if (packages && packages.dim)
585             {
586                 // import [std].stdio;
587                 this.ident = (*packages)[0];
588             }
589             else
590             {
591                 // import [foo];
592                 this.ident = id;
593             }
594         }
595         void addAlias(Identifier name, Identifier _alias)
596         {
597             if (isstatic)
598                 error("cannot have an import bind list");
599             if (!aliasId)
600                 this.ident = null;
601 
602             names.push(name);
603             aliases.push(_alias);
604         }
605 
606         override void accept(Visitor v)
607         {
608             v.visit(this);
609         }
610     }
611 
612     extern (C++) abstract class AttribDeclaration : Dsymbol
613     {
614         Dsymbols* decl;
615 
616         final extern (D) this(Dsymbols *decl)
617         {
618             this.decl = decl;
619         }
620 
621         override final inout(AttribDeclaration) isAttribDeclaration() inout
622         {
623             return this;
624         }
625 
626         override void accept(Visitor v)
627         {
628             v.visit(this);
629         }
630     }
631 
632     extern (C++) final class StaticAssert : Dsymbol
633     {
634         Expression exp;
635         Expression msg;
636 
637         extern (D) this(const ref Loc loc, Expression exp, Expression msg)
638         {
639             super(Id.empty);
640             this.loc = loc;
641             this.exp = exp;
642             this.msg = msg;
643         }
644     }
645 
646     extern (C++) final class DebugSymbol : Dsymbol
647     {
648         uint level;
649 
650         extern (D) this(const ref Loc loc, Identifier ident)
651         {
652             super(ident);
653             this.loc = loc;
654         }
655         extern (D) this(const ref Loc loc, uint level)
656         {
657             this.level = level;
658             this.loc = loc;
659         }
660 
661         override void accept(Visitor v)
662         {
663             v.visit(this);
664         }
665     }
666 
667     extern (C++) final class VersionSymbol : Dsymbol
668     {
669         uint level;
670 
671         extern (D) this(const ref Loc loc, Identifier ident)
672         {
673             super(ident);
674             this.loc = loc;
675         }
676         extern (D) this(const ref Loc loc, uint level)
677         {
678             this.level = level;
679             this.loc = loc;
680         }
681 
682         override void accept(Visitor v)
683         {
684             v.visit(this);
685         }
686     }
687 
688     extern (C++) class VarDeclaration : Declaration
689     {
690         Type type;
691         Initializer _init;
692         enum AdrOnStackNone = ~0u;
693         uint ctfeAdrOnStack;
694         uint sequenceNumber;
695         __gshared uint nextSequenceNumber;
696 
697         final extern (D) this(const ref Loc loc, Type type, Identifier id, Initializer _init, StorageClass st = STC.undefined_)
698         {
699             super(id);
700             this.type = type;
701             this._init = _init;
702             this.loc = loc;
703             this.storage_class = st;
704             sequenceNumber = ++nextSequenceNumber;
705             ctfeAdrOnStack = AdrOnStackNone;
706         }
707 
708         override final inout(VarDeclaration) isVarDeclaration() inout
709         {
710             return this;
711         }
712 
713         override void accept(Visitor v)
714         {
715             v.visit(this);
716         }
717     }
718 
719     extern (C++) struct Ensure
720     {
721         Identifier id;
722         Statement ensure;
723     }
724 
725     extern (C++) class FuncDeclaration : Declaration
726     {
727         Statement fbody;
728         Statements* frequires;
729         Ensures* fensures;
730         Loc endloc;
731         StorageClass storage_class;
732         Type type;
733         bool inferRetType;
734         ForeachStatement fes;
735         FuncDeclaration overnext0;
736 
737         final extern (D) this(const ref Loc loc, Loc endloc, Identifier id, StorageClass storage_class, Type type)
738         {
739             super(id);
740             this.storage_class = storage_class;
741             this.type = type;
742             if (type)
743             {
744                 // Normalize storage_class, because function-type related attributes
745                 // are already set in the 'type' in parsing phase.
746                 this.storage_class &= ~(STC.TYPECTOR | STC.FUNCATTR);
747             }
748             this.loc = loc;
749             this.endloc = endloc;
750             inferRetType = (type && type.nextOf() is null);
751         }
752 
753         FuncLiteralDeclaration isFuncLiteralDeclaration()
754         {
755             return null;
756         }
757 
758         override bool isOverloadable() const
759         {
760             return true;
761         }
762 
763         override final inout(FuncDeclaration) isFuncDeclaration() inout
764         {
765             return this;
766         }
767 
768         override void accept(Visitor v)
769         {
770             v.visit(this);
771         }
772     }
773 
774     extern (C++) final class AliasDeclaration : Declaration
775     {
776         Dsymbol aliassym;
777 
778         extern (D) this(const ref Loc loc, Identifier id, Dsymbol s)
779         {
780             super(id);
781             this.loc = loc;
782             this.aliassym = s;
783         }
784 
785         extern (D) this(const ref Loc loc, Identifier id, Type type)
786         {
787             super(id);
788             this.loc = loc;
789             this.type = type;
790         }
791 
792         override bool isOverloadable() const
793         {
794             //assume overloadable until alias is resolved;
795             // should be modified when semantic analysis is added
796             return true;
797         }
798 
799         override void accept(Visitor v)
800         {
801             v.visit(this);
802         }
803     }
804 
805     extern (C++) final class TupleDeclaration : Declaration
806     {
807         Objects* objects;
808 
809         extern (D) this(const ref Loc loc, Identifier id, Objects* objects)
810         {
811             super(id);
812             this.loc = loc;
813             this.objects = objects;
814         }
815 
816         override void accept(Visitor v)
817         {
818             v.visit(this);
819         }
820     }
821 
822     extern (C++) final class FuncLiteralDeclaration : FuncDeclaration
823     {
824         TOK tok;
825 
826         extern (D) this(const ref Loc loc, Loc endloc, Type type, TOK tok, ForeachStatement fes, Identifier id = null)
827         {
828             super(loc, endloc, null, STC.undefined_, type);
829             this.ident = id ? id : Id.empty;
830             this.tok = tok;
831             this.fes = fes;
832         }
833 
834         override inout(FuncLiteralDeclaration) isFuncLiteralDeclaration() inout
835         {
836             return this;
837         }
838 
839         override void accept(Visitor v)
840         {
841             v.visit(this);
842         }
843     }
844 
845     extern (C++) final class PostBlitDeclaration : FuncDeclaration
846     {
847         extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc, Identifier id)
848         {
849             super(loc, endloc, id, stc, null);
850         }
851 
852         override void accept(Visitor v)
853         {
854             v.visit(this);
855         }
856     }
857 
858     extern (C++) final class CtorDeclaration : FuncDeclaration
859     {
860         extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc, Type type, bool isCopyCtor = false)
861         {
862             super(loc, endloc, Id.ctor, stc, type);
863         }
864 
865         override void accept(Visitor v)
866         {
867             v.visit(this);
868         }
869     }
870 
871     extern (C++) final class DtorDeclaration : FuncDeclaration
872     {
873         extern (D) this(const ref Loc loc, Loc endloc)
874         {
875             super(loc, endloc, Id.dtor, STC.undefined_, null);
876         }
877         extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc, Identifier id)
878         {
879             super(loc, endloc, id, stc, null);
880         }
881 
882         override void accept(Visitor v)
883         {
884             v.visit(this);
885         }
886     }
887 
888     extern (C++) final class InvariantDeclaration : FuncDeclaration
889     {
890         extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc, Identifier id, Statement fbody)
891         {
892             super(loc, endloc, id ? id : Identifier.generateId("__invariant"), stc, null);
893             this.fbody = fbody;
894         }
895 
896         override void accept(Visitor v)
897         {
898             v.visit(this);
899         }
900     }
901 
902     extern (C++) final class UnitTestDeclaration : FuncDeclaration
903     {
904         char* codedoc;
905 
906         extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc, char* codedoc)
907         {
908             super(loc, endloc, Identifier.generateIdWithLoc("__unittest", loc), stc, null);
909             this.codedoc = codedoc;
910         }
911 
912         override void accept(Visitor v)
913         {
914             v.visit(this);
915         }
916     }
917 
918     extern (C++) final class NewDeclaration : FuncDeclaration
919     {
920         ParameterList parameterList;
921 
922         extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc, ref ParameterList parameterList)
923         {
924             super(loc, endloc, Id.classNew, STC.static_ | stc, null);
925             this.parameterList = parameterList;
926         }
927 
928         override void accept(Visitor v)
929         {
930             v.visit(this);
931         }
932     }
933 
934     extern (C++) class StaticCtorDeclaration : FuncDeclaration
935     {
936         final extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc)
937         {
938             super(loc, endloc, Identifier.generateIdWithLoc("_staticCtor", loc), STC.static_ | stc, null);
939         }
940         final extern (D) this(const ref Loc loc, Loc endloc, string name, StorageClass stc)
941         {
942             super(loc, endloc, Identifier.generateIdWithLoc(name, loc), STC.static_ | stc, null);
943         }
944 
945         override void accept(Visitor v)
946         {
947             v.visit(this);
948         }
949     }
950 
951     extern (C++) class StaticDtorDeclaration : FuncDeclaration
952     {
953         final extern (D) this()(Loc loc, Loc endloc, StorageClass stc)
954         {
955             super(loc, endloc, Identifier.generateIdWithLoc("__staticDtor", loc), STC.static_ | stc, null);
956         }
957         final extern (D) this(const ref Loc loc, Loc endloc, string name, StorageClass stc)
958         {
959             super(loc, endloc, Identifier.generateIdWithLoc(name, loc), STC.static_ | stc, null);
960         }
961 
962         override void accept(Visitor v)
963         {
964             v.visit(this);
965         }
966     }
967 
968     extern (C++) final class SharedStaticCtorDeclaration : StaticCtorDeclaration
969     {
970         extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc)
971         {
972             super(loc, endloc, "_sharedStaticCtor", stc);
973         }
974 
975         override void accept(Visitor v)
976         {
977             v.visit(this);
978         }
979     }
980 
981     extern (C++) final class SharedStaticDtorDeclaration : StaticDtorDeclaration
982     {
983         extern (D) this(const ref Loc loc, Loc endloc, StorageClass stc)
984         {
985             super(loc, endloc, "_sharedStaticDtor", stc);
986         }
987 
988         override void accept(Visitor v)
989         {
990             v.visit(this);
991         }
992     }
993 
994     extern (C++) class Package : ScopeDsymbol
995     {
996         PKG isPkgMod;
997         uint tag;
998 
999         final extern (D) this(Identifier ident)
1000         {
1001             super(ident);
1002             this.isPkgMod = PKG.unknown;
1003             __gshared uint packageTag;
1004             this.tag = packageTag++;
1005         }
1006 
1007         override void accept(Visitor v)
1008         {
1009             v.visit(this);
1010         }
1011     }
1012 
1013     extern (C++) final class EnumDeclaration : ScopeDsymbol
1014     {
1015         Type type;
1016         Type memtype;
1017         Prot protection;
1018 
1019         extern (D) this(const ref Loc loc, Identifier id, Type memtype)
1020         {
1021             super(id);
1022             this.loc = loc;
1023             type = new TypeEnum(this);
1024             this.memtype = memtype;
1025             protection = Prot(Prot.Kind.undefined);
1026         }
1027 
1028         override void accept(Visitor v)
1029         {
1030             v.visit(this);
1031         }
1032     }
1033 
1034     extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
1035     {
1036         Prot protection;
1037         Sizeok sizeok;
1038         Type type;
1039 
1040         final extern (D) this(const ref Loc loc, Identifier id)
1041         {
1042             super(id);
1043             this.loc = loc;
1044             protection = Prot(Prot.Kind.public_);
1045             sizeok = Sizeok.none;
1046         }
1047 
1048         override final inout(AggregateDeclaration) isAggregateDeclaration() inout
1049         {
1050             return this;
1051         }
1052 
1053         override void accept(Visitor v)
1054         {
1055             v.visit(this);
1056         }
1057     }
1058 
1059     extern (C++) final class TemplateDeclaration : ScopeDsymbol
1060     {
1061         TemplateParameters* parameters;
1062         TemplateParameters* origParameters;
1063         Expression constraint;
1064         bool literal;
1065         bool ismixin;
1066         bool isstatic;
1067         Prot protection;
1068         Dsymbol onemember;
1069 
1070         extern (D) this(const ref Loc loc, Identifier id, TemplateParameters* parameters, Expression constraint, Dsymbols* decldefs, bool ismixin = false, bool literal = false)
1071         {
1072             super(id);
1073             this.loc = loc;
1074             this.parameters = parameters;
1075             this.origParameters = parameters;
1076             this.members = decldefs;
1077             this.literal = literal;
1078             this.ismixin = ismixin;
1079             this.isstatic = true;
1080             this.protection = Prot(Prot.Kind.undefined);
1081 
1082             if (members && ident)
1083             {
1084                 Dsymbol s;
1085                 if (Dsymbol.oneMembers(*members, &s, ident) && s)
1086                 {
1087                     onemember = s;
1088                     s.parent = this;
1089                 }
1090             }
1091         }
1092 
1093         override bool isOverloadable() const
1094         {
1095             return true;
1096         }
1097 
1098         override inout(TemplateDeclaration) isTemplateDeclaration () inout
1099         {
1100             return this;
1101         }
1102 
1103         override void accept(Visitor v)
1104         {
1105             v.visit(this);
1106         }
1107     }
1108 
1109     extern (C++) class TemplateInstance : ScopeDsymbol
1110     {
1111         Identifier name;
1112         Objects* tiargs;
1113         Dsymbol tempdecl;
1114         bool semantictiargsdone;
1115         bool havetempdecl;
1116         TemplateInstance inst;
1117 
1118         final extern (D) this(const ref Loc loc, Identifier ident, Objects* tiargs)
1119         {
1120             super(null);
1121             this.loc = loc;
1122             this.name = ident;
1123             this.tiargs = tiargs;
1124         }
1125 
1126         final extern (D) this(const ref Loc loc, TemplateDeclaration td, Objects* tiargs)
1127         {
1128             super(null);
1129             this.loc = loc;
1130             this.name = td.ident;
1131             this.tempdecl = td;
1132             this.semantictiargsdone = true;
1133             this.havetempdecl = true;
1134         }
1135 
1136         override final inout(TemplateInstance) isTemplateInstance() inout
1137         {
1138             return this;
1139         }
1140 
1141         Objects* arraySyntaxCopy(Objects* objs)
1142         {
1143             Objects* a = null;
1144             if (objs)
1145             {
1146                 a = new Objects();
1147                 a.setDim(objs.dim);
1148                 for (size_t i = 0; i < objs.dim; i++)
1149                     (*a)[i] = objectSyntaxCopy((*objs)[i]);
1150             }
1151             return a;
1152         }
1153 
1154         RootObject objectSyntaxCopy(RootObject o)
1155         {
1156             if (!o)
1157                 return null;
1158             if (Type t = isType(o))
1159                 return t.syntaxCopy();
1160             if (Expression e = isExpression(o))
1161                 return e.syntaxCopy();
1162             return o;
1163         }
1164 
1165         override Dsymbol syntaxCopy(Dsymbol s)
1166         {
1167             TemplateInstance ti = s ? cast(TemplateInstance)s : new TemplateInstance(loc, name, null);
1168             ti.tiargs = arraySyntaxCopy(tiargs);
1169             TemplateDeclaration td;
1170             if (inst && tempdecl && (td = tempdecl.isTemplateDeclaration()) !is null)
1171                 td.ScopeDsymbol.syntaxCopy(ti);
1172             else
1173                 ScopeDsymbol.syntaxCopy(ti);
1174             return ti;
1175         }
1176 
1177         override void accept(Visitor v)
1178         {
1179             v.visit(this);
1180         }
1181     }
1182 
1183     extern (C++) final class Nspace : ScopeDsymbol
1184     {
1185         /**
1186          * Namespace identifier resolved during semantic.
1187          */
1188         Expression identExp;
1189 
1190         extern (D) this(const ref Loc loc, Identifier ident, Expression identExp, Dsymbols* members)
1191         {
1192             super(ident);
1193             this.loc = loc;
1194             this.members = members;
1195             this.identExp = identExp;
1196         }
1197 
1198         override void accept(Visitor v)
1199         {
1200             v.visit(this);
1201         }
1202     }
1203 
1204     extern (C++) final class CompileDeclaration : AttribDeclaration
1205     {
1206         Expressions* exps;
1207 
1208         extern (D) this(const ref Loc loc, Expressions* exps)
1209         {
1210             super(null);
1211             this.loc = loc;
1212             this.exps = exps;
1213         }
1214 
1215         override void accept(Visitor v)
1216         {
1217             v.visit(this);
1218         }
1219     }
1220 
1221     extern (C++) final class UserAttributeDeclaration : AttribDeclaration
1222     {
1223         Expressions* atts;
1224 
1225         extern (D) this(Expressions* atts, Dsymbols* decl)
1226         {
1227             super(decl);
1228             this.atts = atts;
1229         }
1230 
1231         extern (D) static Expressions* concat(Expressions* udas1, Expressions* udas2)
1232         {
1233             Expressions* udas;
1234             if (!udas1 || udas1.dim == 0)
1235                 udas = udas2;
1236             else if (!udas2 || udas2.dim == 0)
1237                 udas = udas1;
1238             else
1239             {
1240                 udas = new Expressions(2);
1241                 (*udas)[0] = new TupleExp(Loc.initial, udas1);
1242                 (*udas)[1] = new TupleExp(Loc.initial, udas2);
1243             }
1244             return udas;
1245         }
1246 
1247         override void accept(Visitor v)
1248         {
1249             v.visit(this);
1250         }
1251     }
1252 
1253     extern (C++) final class LinkDeclaration : AttribDeclaration
1254     {
1255         LINK linkage;
1256 
1257         extern (D) this(LINK p, Dsymbols* decl)
1258         {
1259             super(decl);
1260             linkage = p;
1261         }
1262 
1263         override void accept(Visitor v)
1264         {
1265             v.visit(this);
1266         }
1267     }
1268 
1269     extern (C++) final class AnonDeclaration : AttribDeclaration
1270     {
1271         bool isunion;
1272 
1273         extern (D) this(const ref Loc loc, bool isunion, Dsymbols* decl)
1274         {
1275             super(decl);
1276             this.loc = loc;
1277             this.isunion = isunion;
1278         }
1279 
1280         override void accept(Visitor v)
1281         {
1282             v.visit(this);
1283         }
1284     }
1285 
1286     extern (C++) final class AlignDeclaration : AttribDeclaration
1287     {
1288         Expression ealign;
1289 
1290         extern (D) this(const ref Loc loc, Expression ealign, Dsymbols* decl)
1291         {
1292             super(decl);
1293             this.loc = loc;
1294             this.ealign = ealign;
1295         }
1296 
1297         override void accept(Visitor v)
1298         {
1299             v.visit(this);
1300         }
1301     }
1302 
1303     extern (C++) final class CPPMangleDeclaration : AttribDeclaration
1304     {
1305         CPPMANGLE cppmangle;
1306 
1307         extern (D) this(CPPMANGLE p, Dsymbols* decl)
1308         {
1309             super(decl);
1310             cppmangle = p;
1311         }
1312 
1313         override void accept(Visitor v)
1314         {
1315             v.visit(this);
1316         }
1317     }
1318 
1319     extern (C++) final class CPPNamespaceDeclaration : AttribDeclaration
1320     {
1321         Expression exp;
1322 
1323         extern (D) this(Identifier ident, Dsymbols* decl)
1324         {
1325             super(decl);
1326             this.ident = ident;
1327         }
1328 
1329         extern (D) this(Expression exp, Dsymbols* decl)
1330         {
1331             super(decl);
1332             this.exp = exp;
1333         }
1334 
1335         override void accept(Visitor v)
1336         {
1337             v.visit(this);
1338         }
1339     }
1340 
1341     extern (C++) final class ProtDeclaration : AttribDeclaration
1342     {
1343         Prot protection;
1344         Identifiers* pkg_identifiers;
1345 
1346         extern (D) this(const ref Loc loc, Prot p, Dsymbols* decl)
1347         {
1348             super(decl);
1349             this.loc = loc;
1350             this.protection = p;
1351         }
1352         extern (D) this(const ref Loc loc, Identifiers* pkg_identifiers, Dsymbols* decl)
1353         {
1354             super(decl);
1355             this.loc = loc;
1356             this.protection.kind = Prot.Kind.package_;
1357             this.protection.pkg = null;
1358             this.pkg_identifiers = pkg_identifiers;
1359         }
1360 
1361         override void accept(Visitor v)
1362         {
1363             v.visit(this);
1364         }
1365     }
1366 
1367     extern (C++) final class PragmaDeclaration : AttribDeclaration
1368     {
1369         Expressions* args;
1370 
1371         extern (D) this(const ref Loc loc, Identifier ident, Expressions* args, Dsymbols* decl)
1372         {
1373             super(decl);
1374             this.loc = loc;
1375             this.ident = ident;
1376             this.args = args;
1377         }
1378 
1379         override void accept(Visitor v)
1380         {
1381             v.visit(this);
1382         }
1383     }
1384 
1385     extern (C++) class StorageClassDeclaration : AttribDeclaration
1386     {
1387         StorageClass stc;
1388 
1389         final extern (D) this(StorageClass stc, Dsymbols* decl)
1390         {
1391             super(decl);
1392             this.stc = stc;
1393         }
1394 
1395         override void accept(Visitor v)
1396         {
1397             v.visit(this);
1398         }
1399     }
1400 
1401     extern (C++) class ConditionalDeclaration : AttribDeclaration
1402     {
1403         Condition condition;
1404         Dsymbols* elsedecl;
1405 
1406         final extern (D) this(Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
1407         {
1408             super(decl);
1409             this.condition = condition;
1410             this.elsedecl = elsedecl;
1411         }
1412 
1413         override void accept(Visitor v)
1414         {
1415             v.visit(this);
1416         }
1417     }
1418 
1419     extern (C++) final class DeprecatedDeclaration : StorageClassDeclaration
1420     {
1421         Expression msg;
1422 
1423         extern (D) this(Expression msg, Dsymbols* decl)
1424         {
1425             super(STC.deprecated_, decl);
1426             this.msg = msg;
1427         }
1428 
1429         override void accept(Visitor v)
1430         {
1431             v.visit(this);
1432         }
1433     }
1434 
1435     extern (C++) final class StaticIfDeclaration : ConditionalDeclaration
1436     {
1437         extern (D) this(Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
1438         {
1439             super(condition, decl, elsedecl);
1440         }
1441 
1442         override void accept(Visitor v)
1443         {
1444             v.visit(this);
1445         }
1446     }
1447 
1448     extern (C++) final class StaticForeachDeclaration : AttribDeclaration
1449     {
1450         StaticForeach sfe;
1451 
1452         extern (D) this(StaticForeach sfe, Dsymbols* decl)
1453         {
1454             super(decl);
1455             this.sfe = sfe;
1456         }
1457 
1458         override void accept(Visitor v)
1459         {
1460             v.visit(this);
1461         }
1462     }
1463 
1464     extern (C++) final class EnumMember : VarDeclaration
1465     {
1466         Expression origValue;
1467         Type origType;
1468 
1469         @property ref value() { return (cast(ExpInitializer)_init).exp; }
1470 
1471         extern (D) this(const ref Loc loc, Identifier id, Expression value, Type origType)
1472         {
1473             super(loc, null, id ? id : Id.empty, new ExpInitializer(loc, value));
1474             this.origValue = value;
1475             this.origType = origType;
1476         }
1477 
1478         extern(D) this(const ref Loc loc, Identifier id, Expression value, Type memtype,
1479             StorageClass stc, UserAttributeDeclaration uad, DeprecatedDeclaration dd)
1480         {
1481             this(loc, id, value, memtype);
1482             storage_class = stc;
1483             userAttribDecl = uad;
1484             // just ignore `dd`
1485         }
1486 
1487         override void accept(Visitor v)
1488         {
1489             v.visit(this);
1490         }
1491     }
1492 
1493     extern (C++) final class Module : Package
1494     {
1495         extern (C++) __gshared AggregateDeclaration moduleinfo;
1496 
1497         const FileName srcfile;
1498         const(char)* arg;
1499 
1500         extern (D) this(const(char)* filename, Identifier ident, int doDocComment, int doHdrGen)
1501         {
1502             super(ident);
1503             this.arg = filename;
1504             srcfile = FileName(FileName.defaultExt(filename.toDString, global.mars_ext));
1505         }
1506 
1507         override void accept(Visitor v)
1508         {
1509             v.visit(this);
1510         }
1511     }
1512 
1513     extern (C++) class StructDeclaration : AggregateDeclaration
1514     {
1515         int zeroInit;
1516         StructPOD ispod;
1517 
1518         final extern (D) this(const ref Loc loc, Identifier id, bool inObject)
1519         {
1520             super(loc, id);
1521             zeroInit = 0;
1522             ispod = StructPOD.fwd;
1523             type = new TypeStruct(this);
1524             if (inObject)
1525             {
1526                 if (id == Id.ModuleInfo && !Module.moduleinfo)
1527                     Module.moduleinfo = this;
1528             }
1529         }
1530 
1531         override void accept(Visitor v)
1532         {
1533             v.visit(this);
1534         }
1535     }
1536 
1537     extern (C++) final class UnionDeclaration : StructDeclaration
1538     {
1539         extern (D) this(const ref Loc loc, Identifier id)
1540         {
1541             super(loc, id, false);
1542         }
1543 
1544         override void accept(Visitor v)
1545         {
1546             v.visit(this);
1547         }
1548     }
1549 
1550     extern (C++) class ClassDeclaration : AggregateDeclaration
1551     {
1552         extern (C++) __gshared
1553         {
1554             // Names found by reading object.d in druntime
1555             ClassDeclaration object;
1556             ClassDeclaration throwable;
1557             ClassDeclaration exception;
1558             ClassDeclaration errorException;
1559             ClassDeclaration cpp_type_info_ptr;   // Object.__cpp_type_info_ptr
1560         }
1561 
1562         BaseClasses* baseclasses;
1563         Baseok baseok;
1564 
1565         final extern (D) this(const ref Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
1566         {
1567             if(!id)
1568                 id = Identifier.generateId("__anonclass");
1569             assert(id);
1570 
1571             super(loc, id);
1572 
1573             __gshared const(char)* msg = "only object.d can define this reserved class name";
1574 
1575             if (baseclasses)
1576             {
1577                 // Actually, this is a transfer
1578                 this.baseclasses = baseclasses;
1579             }
1580             else
1581                 this.baseclasses = new BaseClasses();
1582 
1583             this.members = members;
1584 
1585             //printf("ClassDeclaration(%s), dim = %d\n", id.toChars(), this.baseclasses.dim);
1586 
1587             // For forward references
1588             type = new TypeClass(this);
1589 
1590             if (id)
1591             {
1592                 // Look for special class names
1593                 if (id == Id.__sizeof || id == Id.__xalignof || id == Id._mangleof)
1594                     error("illegal class name");
1595 
1596                 // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
1597                 if (id.toChars()[0] == 'T')
1598                 {
1599                     if (id == Id.TypeInfo)
1600                     {
1601                         if (!inObject)
1602                             error("%s", msg);
1603                         Type.dtypeinfo = this;
1604                     }
1605                     if (id == Id.TypeInfo_Class)
1606                     {
1607                         if (!inObject)
1608                             error("%s", msg);
1609                         Type.typeinfoclass = this;
1610                     }
1611                     if (id == Id.TypeInfo_Interface)
1612                     {
1613                         if (!inObject)
1614                             error("%s", msg);
1615                         Type.typeinfointerface = this;
1616                     }
1617                     if (id == Id.TypeInfo_Struct)
1618                     {
1619                         if (!inObject)
1620                             error("%s", msg);
1621                         Type.typeinfostruct = this;
1622                     }
1623                     if (id == Id.TypeInfo_Pointer)
1624                     {
1625                         if (!inObject)
1626                             error("%s", msg);
1627                         Type.typeinfopointer = this;
1628                     }
1629                     if (id == Id.TypeInfo_Array)
1630                     {
1631                         if (!inObject)
1632                             error("%s", msg);
1633                         Type.typeinfoarray = this;
1634                     }
1635                     if (id == Id.TypeInfo_StaticArray)
1636                     {
1637                         //if (!inObject)
1638                         //    Type.typeinfostaticarray.error("%s", msg);
1639                         Type.typeinfostaticarray = this;
1640                     }
1641                     if (id == Id.TypeInfo_AssociativeArray)
1642                     {
1643                         if (!inObject)
1644                             error("%s", msg);
1645                         Type.typeinfoassociativearray = this;
1646                     }
1647                     if (id == Id.TypeInfo_Enum)
1648                     {
1649                         if (!inObject)
1650                             error("%s", msg);
1651                         Type.typeinfoenum = this;
1652                     }
1653                     if (id == Id.TypeInfo_Function)
1654                     {
1655                         if (!inObject)
1656                             error("%s", msg);
1657                         Type.typeinfofunction = this;
1658                     }
1659                     if (id == Id.TypeInfo_Delegate)
1660                     {
1661                         if (!inObject)
1662                             error("%s", msg);
1663                         Type.typeinfodelegate = this;
1664                     }
1665                     if (id == Id.TypeInfo_Tuple)
1666                     {
1667                         if (!inObject)
1668                             error("%s", msg);
1669                         Type.typeinfotypelist = this;
1670                     }
1671                     if (id == Id.TypeInfo_Const)
1672                     {
1673                         if (!inObject)
1674                             error("%s", msg);
1675                         Type.typeinfoconst = this;
1676                     }
1677                     if (id == Id.TypeInfo_Invariant)
1678                     {
1679                         if (!inObject)
1680                             error("%s", msg);
1681                         Type.typeinfoinvariant = this;
1682                     }
1683                     if (id == Id.TypeInfo_Shared)
1684                     {
1685                         if (!inObject)
1686                             error("%s", msg);
1687                         Type.typeinfoshared = this;
1688                     }
1689                     if (id == Id.TypeInfo_Wild)
1690                     {
1691                         if (!inObject)
1692                             error("%s", msg);
1693                         Type.typeinfowild = this;
1694                     }
1695                     if (id == Id.TypeInfo_Vector)
1696                     {
1697                         if (!inObject)
1698                             error("%s", msg);
1699                         Type.typeinfovector = this;
1700                     }
1701                 }
1702 
1703                 if (id == Id.Object)
1704                 {
1705                     if (!inObject)
1706                         error("%s", msg);
1707                     object = this;
1708                 }
1709 
1710                 if (id == Id.Throwable)
1711                 {
1712                     if (!inObject)
1713                         error("%s", msg);
1714                     throwable = this;
1715                 }
1716                 if (id == Id.Exception)
1717                 {
1718                     if (!inObject)
1719                         error("%s", msg);
1720                     exception = this;
1721                 }
1722                 if (id == Id.Error)
1723                 {
1724                     if (!inObject)
1725                         error("%s", msg);
1726                     errorException = this;
1727                 }
1728                 if (id == Id.cpp_type_info_ptr)
1729                 {
1730                     if (!inObject)
1731                         error("%s", msg);
1732                     cpp_type_info_ptr = this;
1733                 }
1734             }
1735             baseok = Baseok.none;
1736         }
1737 
1738         override final inout(ClassDeclaration) isClassDeclaration() inout
1739         {
1740             return this;
1741         }
1742 
1743         override void accept(Visitor v)
1744         {
1745             v.visit(this);
1746         }
1747     }
1748 
1749     extern (C++) class InterfaceDeclaration : ClassDeclaration
1750     {
1751         final extern (D) this(const ref Loc loc, Identifier id, BaseClasses* baseclasses)
1752         {
1753             super(loc, id, baseclasses, null, false);
1754         }
1755 
1756         override void accept(Visitor v)
1757         {
1758             v.visit(this);
1759         }
1760     }
1761 
1762     extern (C++) class TemplateMixin : TemplateInstance
1763     {
1764         TypeQualified tqual;
1765 
1766         extern (D) this(const ref Loc loc, Identifier ident, TypeQualified tqual, Objects *tiargs)
1767         {
1768             super(loc,
1769                   tqual.idents.dim ? cast(Identifier)tqual.idents[tqual.idents.dim - 1] : (cast(TypeIdentifier)tqual).ident,
1770                   tiargs ? tiargs : new Objects());
1771             this.ident = ident;
1772             this.tqual = tqual;
1773         }
1774 
1775         override void accept(Visitor v)
1776         {
1777             v.visit(this);
1778         }
1779     }
1780 
1781     extern (C++) struct ParameterList
1782     {
1783         Parameters* parameters;
1784         StorageClass stc;                   // storage class of ...
1785         VarArg varargs = VarArg.none;
1786 
1787         this(Parameters* parameters, VarArg varargs = VarArg.none, StorageClass stc = 0)
1788         {
1789             this.parameters = parameters;
1790             this.varargs = varargs;
1791             this.stc = stc;
1792         }
1793     }
1794 
1795     extern (C++) final class Parameter : ASTNode
1796     {
1797         StorageClass storageClass;
1798         Type type;
1799         Identifier ident;
1800         Expression defaultArg;
1801         UserAttributeDeclaration userAttribDecl; // user defined attributes
1802 
1803         extern (D) alias ForeachDg = int delegate(size_t idx, Parameter param);
1804 
1805         final extern (D) this(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg, UserAttributeDeclaration userAttribDecl)
1806         {
1807             this.storageClass = storageClass;
1808             this.type = type;
1809             this.ident = ident;
1810             this.defaultArg = defaultArg;
1811             this.userAttribDecl = userAttribDecl;
1812         }
1813 
1814         static size_t dim(Parameters* parameters)
1815         {
1816            size_t nargs = 0;
1817 
1818             int dimDg(size_t n, Parameter p)
1819             {
1820                 ++nargs;
1821                 return 0;
1822             }
1823 
1824             _foreach(parameters, &dimDg);
1825             return nargs;
1826         }
1827 
1828         static Parameter getNth(Parameters* parameters, size_t nth, size_t* pn = null)
1829         {
1830             Parameter param;
1831 
1832             int getNthParamDg(size_t n, Parameter p)
1833             {
1834                 if (n == nth)
1835                 {
1836                     param = p;
1837                     return 1;
1838                 }
1839                 return 0;
1840             }
1841 
1842             int res = _foreach(parameters, &getNthParamDg);
1843             return res ? param : null;
1844         }
1845 
1846         extern (D) static int _foreach(Parameters* parameters, scope ForeachDg dg, size_t* pn = null)
1847         {
1848             assert(dg);
1849             if (!parameters)
1850                 return 0;
1851 
1852             size_t n = pn ? *pn : 0; // take over index
1853             int result = 0;
1854             foreach (i; 0 .. parameters.dim)
1855             {
1856                 Parameter p = (*parameters)[i];
1857                 Type t = p.type.toBasetype();
1858 
1859                 if (t.ty == Ttuple)
1860                 {
1861                     TypeTuple tu = cast(TypeTuple)t;
1862                     result = _foreach(tu.arguments, dg, &n);
1863                 }
1864                 else
1865                     result = dg(n++, p);
1866 
1867                 if (result)
1868                     break;
1869             }
1870 
1871             if (pn)
1872                 *pn = n; // update index
1873             return result;
1874         }
1875 
1876         Parameter syntaxCopy()
1877         {
1878             return new Parameter(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null, userAttribDecl ? cast(UserAttributeDeclaration) userAttribDecl.syntaxCopy(null) : null);
1879         }
1880 
1881         override void accept(Visitor v)
1882         {
1883             v.visit(this);
1884         }
1885 
1886         static Parameters* arraySyntaxCopy(Parameters* parameters)
1887         {
1888             Parameters* params = null;
1889             if (parameters)
1890             {
1891                 params = new Parameters();
1892                 params.setDim(parameters.dim);
1893                 for (size_t i = 0; i < params.dim; i++)
1894                     (*params)[i] = (*parameters)[i].syntaxCopy();
1895             }
1896             return params;
1897         }
1898 
1899     }
1900 
1901     enum STMT : ubyte
1902     {
1903         Error,
1904         Peel,
1905         Exp, DtorExp,
1906         Compile,
1907         Compound, CompoundDeclaration, CompoundAsm,
1908         UnrolledLoop,
1909         Scope,
1910         Forwarding,
1911         While,
1912         Do,
1913         For,
1914         Foreach,
1915         ForeachRange,
1916         If,
1917         Conditional,
1918         StaticForeach,
1919         Pragma,
1920         StaticAssert,
1921         Switch,
1922         Case,
1923         CaseRange,
1924         Default,
1925         GotoDefault,
1926         GotoCase,
1927         SwitchError,
1928         Return,
1929         Break,
1930         Continue,
1931         Synchronized,
1932         With,
1933         TryCatch,
1934         TryFinally,
1935         ScopeGuard,
1936         Throw,
1937         Debug,
1938         Goto,
1939         Label,
1940         Asm, InlineAsm, GccAsm,
1941         Import,
1942     }
1943 
1944     extern (C++) abstract class Statement : ASTNode
1945     {
1946         Loc loc;
1947         STMT stmt;
1948 
1949         final extern (D) this(const ref Loc loc, STMT stmt)
1950         {
1951             this.loc = loc;
1952             this.stmt = stmt;
1953         }
1954 
1955         nothrow pure @nogc
1956         inout(ExpStatement) isExpStatement() inout { return stmt == STMT.Exp ? cast(typeof(return))this : null; }
1957 
1958         nothrow pure @nogc
1959         inout(CompoundStatement) isCompoundStatement() inout { return stmt == STMT.Compound ? cast(typeof(return))this : null; }
1960 
1961         nothrow pure @nogc
1962         inout(ReturnStatement) isReturnStatement() inout { return stmt == STMT.Return ? cast(typeof(return))this : null; }
1963 
1964         override void accept(Visitor v)
1965         {
1966             v.visit(this);
1967         }
1968     }
1969 
1970     extern (C++) final class ImportStatement : Statement
1971     {
1972         Dsymbols* imports;
1973 
1974         extern (D) this(const ref Loc loc, Dsymbols* imports)
1975         {
1976             super(loc, STMT.Import);
1977             this.imports = imports;
1978         }
1979 
1980         override void accept(Visitor v)
1981         {
1982             v.visit(this);
1983         }
1984     }
1985 
1986     extern (C++) final class ScopeStatement : Statement
1987     {
1988         Statement statement;
1989         Loc endloc;
1990 
1991         extern (D) this(const ref Loc loc, Statement s, Loc endloc)
1992         {
1993             super(loc, STMT.Scope);
1994             this.statement = s;
1995             this.endloc = endloc;
1996         }
1997 
1998         override void accept(Visitor v)
1999         {
2000             v.visit(this);
2001         }
2002     }
2003 
2004     extern (C++) final class ReturnStatement : Statement
2005     {
2006         Expression exp;
2007 
2008         extern (D) this(const ref Loc loc, Expression exp)
2009         {
2010             super(loc, STMT.Return);
2011             this.exp = exp;
2012         }
2013 
2014         override void accept(Visitor v)
2015         {
2016             v.visit(this);
2017         }
2018     }
2019 
2020     extern (C++) final class LabelStatement : Statement
2021     {
2022         Identifier ident;
2023         Statement statement;
2024 
2025         final extern (D) this(const ref Loc loc, Identifier ident, Statement statement)
2026         {
2027             super(loc, STMT.Label);
2028             this.ident = ident;
2029             this.statement = statement;
2030         }
2031 
2032         override void accept(Visitor v)
2033         {
2034             v.visit(this);
2035         }
2036     }
2037 
2038     extern (C++) final class StaticAssertStatement : Statement
2039     {
2040         StaticAssert sa;
2041 
2042         final extern (D) this(StaticAssert sa)
2043         {
2044             super(sa.loc, STMT.StaticAssert);
2045             this.sa = sa;
2046         }
2047 
2048         override void accept(Visitor v)
2049         {
2050             v.visit(this);
2051         }
2052     }
2053 
2054     extern (C++) final class CompileStatement : Statement
2055     {
2056         Expressions* exps;
2057 
2058         final extern (D) this(const ref Loc loc, Expressions* exps)
2059         {
2060             super(loc, STMT.Compile);
2061             this.exps = exps;
2062         }
2063 
2064         override void accept(Visitor v)
2065         {
2066             v.visit(this);
2067         }
2068     }
2069 
2070     extern (C++) final class WhileStatement : Statement
2071     {
2072         Expression condition;
2073         Statement _body;
2074         Loc endloc;
2075 
2076         extern (D) this(const ref Loc loc, Expression c, Statement b, Loc endloc)
2077         {
2078             super(loc, STMT.While);
2079             condition = c;
2080             _body = b;
2081             this.endloc = endloc;
2082         }
2083 
2084         override void accept(Visitor v)
2085         {
2086             v.visit(this);
2087         }
2088     }
2089 
2090     extern (C++) final class ForStatement : Statement
2091     {
2092         Statement _init;
2093         Expression condition;
2094         Expression increment;
2095         Statement _body;
2096         Loc endloc;
2097 
2098         extern (D) this(const ref Loc loc, Statement _init, Expression condition, Expression increment, Statement _body, Loc endloc)
2099         {
2100             super(loc, STMT.For);
2101             this._init = _init;
2102             this.condition = condition;
2103             this.increment = increment;
2104             this._body = _body;
2105             this.endloc = endloc;
2106         }
2107 
2108         override void accept(Visitor v)
2109         {
2110             v.visit(this);
2111         }
2112     }
2113 
2114     extern (C++) final class DoStatement : Statement
2115     {
2116         Statement _body;
2117         Expression condition;
2118         Loc endloc;
2119 
2120         extern (D) this(const ref Loc loc, Statement b, Expression c, Loc endloc)
2121         {
2122             super(loc, STMT.Do);
2123             _body = b;
2124             condition = c;
2125             this.endloc = endloc;
2126         }
2127 
2128         override void accept(Visitor v)
2129         {
2130             v.visit(this);
2131         }
2132     }
2133 
2134     extern (C++) final class ForeachRangeStatement : Statement
2135     {
2136         TOK op;                 // TOK.foreach_ or TOK.foreach_reverse_
2137         Parameter prm;          // loop index variable
2138         Expression lwr;
2139         Expression upr;
2140         Statement _body;
2141         Loc endloc;             // location of closing curly bracket
2142 
2143 
2144         extern (D) this(const ref Loc loc, TOK op, Parameter prm, Expression lwr, Expression upr, Statement _body, Loc endloc)
2145         {
2146             super(loc, STMT.ForeachRange);
2147             this.op = op;
2148             this.prm = prm;
2149             this.lwr = lwr;
2150             this.upr = upr;
2151             this._body = _body;
2152             this.endloc = endloc;
2153         }
2154 
2155         override void accept(Visitor v)
2156         {
2157             v.visit(this);
2158         }
2159     }
2160 
2161     extern (C++) final class ForeachStatement : Statement
2162     {
2163         TOK op;                     // TOK.foreach_ or TOK.foreach_reverse_
2164         Parameters* parameters;     // array of Parameter*'s
2165         Expression aggr;
2166         Statement _body;
2167         Loc endloc;                 // location of closing curly bracket
2168 
2169         extern (D) this(const ref Loc loc, TOK op, Parameters* parameters, Expression aggr, Statement _body, Loc endloc)
2170         {
2171             super(loc, STMT.Foreach);
2172             this.op = op;
2173             this.parameters = parameters;
2174             this.aggr = aggr;
2175             this._body = _body;
2176             this.endloc = endloc;
2177         }
2178 
2179         override void accept(Visitor v)
2180         {
2181             v.visit(this);
2182         }
2183     }
2184 
2185     extern (C++) final class IfStatement : Statement
2186     {
2187         Parameter prm;
2188         Expression condition;
2189         Statement ifbody;
2190         Statement elsebody;
2191         VarDeclaration match;   // for MatchExpression results
2192         Loc endloc;                 // location of closing curly bracket
2193 
2194         extern (D) this(const ref Loc loc, Parameter prm, Expression condition, Statement ifbody, Statement elsebody, Loc endloc)
2195         {
2196             super(loc, STMT.If);
2197             this.prm = prm;
2198             this.condition = condition;
2199             this.ifbody = ifbody;
2200             this.elsebody = elsebody;
2201             this.endloc = endloc;
2202         }
2203 
2204         override void accept(Visitor v)
2205         {
2206             v.visit(this);
2207         }
2208     }
2209 
2210     extern (C++) final class ScopeGuardStatement : Statement
2211     {
2212         TOK tok;
2213         Statement statement;
2214 
2215         extern (D) this(const ref Loc loc, TOK tok, Statement statement)
2216         {
2217             super(loc, STMT.ScopeGuard);
2218             this.tok = tok;
2219             this.statement = statement;
2220         }
2221 
2222         override void accept(Visitor v)
2223         {
2224             v.visit(this);
2225         }
2226     }
2227 
2228     extern (C++) final class ConditionalStatement : Statement
2229     {
2230         Condition condition;
2231         Statement ifbody;
2232         Statement elsebody;
2233 
2234         extern (D) this(const ref Loc loc, Condition condition, Statement ifbody, Statement elsebody)
2235         {
2236             super(loc, STMT.Conditional);
2237             this.condition = condition;
2238             this.ifbody = ifbody;
2239             this.elsebody = elsebody;
2240         }
2241 
2242         override void accept(Visitor v)
2243         {
2244             v.visit(this);
2245         }
2246     }
2247 
2248     extern (C++) final class StaticForeachStatement : Statement
2249     {
2250         StaticForeach sfe;
2251 
2252         extern (D) this(const ref Loc loc, StaticForeach sfe)
2253         {
2254             super(loc, STMT.StaticForeach);
2255             this.sfe = sfe;
2256         }
2257 
2258         override void accept(Visitor v)
2259         {
2260             v.visit(this);
2261         }
2262     }
2263 
2264     extern (C++) final class PragmaStatement : Statement
2265     {
2266         Identifier ident;
2267         Expressions* args;      // array of Expression's
2268         Statement _body;
2269 
2270         extern (D) this(const ref Loc loc, Identifier ident, Expressions* args, Statement _body)
2271         {
2272             super(loc, STMT.Pragma);
2273             this.ident = ident;
2274             this.args = args;
2275             this._body = _body;
2276         }
2277 
2278         override void accept(Visitor v)
2279         {
2280             v.visit(this);
2281         }
2282     }
2283 
2284     extern (C++) final class SwitchStatement : Statement
2285     {
2286         Expression condition;
2287         Statement _body;
2288         bool isFinal;
2289 
2290         extern (D) this(const ref Loc loc, Expression c, Statement b, bool isFinal)
2291         {
2292             super(loc, STMT.Switch);
2293             this.condition = c;
2294             this._body = b;
2295             this.isFinal = isFinal;
2296         }
2297 
2298         override void accept(Visitor v)
2299         {
2300             v.visit(this);
2301         }
2302     }
2303 
2304     extern (C++) final class CaseRangeStatement : Statement
2305     {
2306         Expression first;
2307         Expression last;
2308         Statement statement;
2309 
2310         extern (D) this(const ref Loc loc, Expression first, Expression last, Statement s)
2311         {
2312             super(loc, STMT.CaseRange);
2313             this.first = first;
2314             this.last = last;
2315             this.statement = s;
2316         }
2317 
2318         override void accept(Visitor v)
2319         {
2320             v.visit(this);
2321         }
2322     }
2323 
2324     extern (C++) final class CaseStatement : Statement
2325     {
2326         Expression exp;
2327         Statement statement;
2328 
2329         extern (D) this(const ref Loc loc, Expression exp, Statement s)
2330         {
2331             super(loc, STMT.Case);
2332             this.exp = exp;
2333             this.statement = s;
2334         }
2335 
2336         override void accept(Visitor v)
2337         {
2338             v.visit(this);
2339         }
2340     }
2341 
2342     extern (C++) final class DefaultStatement : Statement
2343     {
2344         Statement statement;
2345 
2346         extern (D) this(const ref Loc loc, Statement s)
2347         {
2348             super(loc, STMT.Default);
2349             this.statement = s;
2350         }
2351 
2352         override void accept(Visitor v)
2353         {
2354             v.visit(this);
2355         }
2356     }
2357 
2358     extern (C++) final class BreakStatement : Statement
2359     {
2360         Identifier ident;
2361 
2362         extern (D) this(const ref Loc loc, Identifier ident)
2363         {
2364             super(loc, STMT.Break);
2365             this.ident = ident;
2366         }
2367 
2368         override void accept(Visitor v)
2369         {
2370             v.visit(this);
2371         }
2372     }
2373 
2374     extern (C++) final class ContinueStatement : Statement
2375     {
2376         Identifier ident;
2377 
2378         extern (D) this(const ref Loc loc, Identifier ident)
2379         {
2380             super(loc, STMT.Continue);
2381             this.ident = ident;
2382         }
2383 
2384         override void accept(Visitor v)
2385         {
2386             v.visit(this);
2387         }
2388     }
2389 
2390     extern (C++) final class GotoDefaultStatement : Statement
2391     {
2392         extern (D) this(const ref Loc loc)
2393         {
2394             super(loc, STMT.GotoDefault);
2395         }
2396 
2397         override void accept(Visitor v)
2398         {
2399             v.visit(this);
2400         }
2401     }
2402 
2403     extern (C++) final class GotoCaseStatement : Statement
2404     {
2405         Expression exp;
2406 
2407         extern (D) this(const ref Loc loc, Expression exp)
2408         {
2409             super(loc, STMT.GotoCase);
2410             this.exp = exp;
2411         }
2412 
2413         override void accept(Visitor v)
2414         {
2415             v.visit(this);
2416         }
2417     }
2418 
2419     extern (C++) final class GotoStatement : Statement
2420     {
2421         Identifier ident;
2422 
2423         extern (D) this(const ref Loc loc, Identifier ident)
2424         {
2425             super(loc, STMT.Goto);
2426             this.ident = ident;
2427         }
2428 
2429         override void accept(Visitor v)
2430         {
2431             v.visit(this);
2432         }
2433     }
2434 
2435     extern (C++) final class SynchronizedStatement : Statement
2436     {
2437         Expression exp;
2438         Statement _body;
2439 
2440         extern (D) this(const ref Loc loc, Expression exp, Statement _body)
2441         {
2442             super(loc, STMT.Synchronized);
2443             this.exp = exp;
2444             this._body = _body;
2445         }
2446 
2447         override void accept(Visitor v)
2448         {
2449             v.visit(this);
2450         }
2451     }
2452 
2453     extern (C++) final class WithStatement : Statement
2454     {
2455         Expression exp;
2456         Statement _body;
2457         Loc endloc;
2458 
2459         extern (D) this(const ref Loc loc, Expression exp, Statement _body, Loc endloc)
2460         {
2461             super(loc, STMT.With);
2462             this.exp = exp;
2463             this._body = _body;
2464             this.endloc = endloc;
2465         }
2466 
2467         override void accept(Visitor v)
2468         {
2469             v.visit(this);
2470         }
2471     }
2472 
2473     extern (C++) final class TryCatchStatement : Statement
2474     {
2475         Statement _body;
2476         Catches* catches;
2477 
2478         extern (D) this(const ref Loc loc, Statement _body, Catches* catches)
2479         {
2480             super(loc, STMT.TryCatch);
2481             this._body = _body;
2482             this.catches = catches;
2483         }
2484 
2485         override void accept(Visitor v)
2486         {
2487             v.visit(this);
2488         }
2489     }
2490 
2491     extern (C++) final class TryFinallyStatement : Statement
2492     {
2493         Statement _body;
2494         Statement finalbody;
2495 
2496         extern (D) this(const ref Loc loc, Statement _body, Statement finalbody)
2497         {
2498             super(loc, STMT.TryFinally);
2499             this._body = _body;
2500             this.finalbody = finalbody;
2501         }
2502 
2503         override void accept(Visitor v)
2504         {
2505             v.visit(this);
2506         }
2507     }
2508 
2509     extern (C++) final class ThrowStatement : Statement
2510     {
2511         Expression exp;
2512 
2513         extern (D) this(const ref Loc loc, Expression exp)
2514         {
2515             super(loc, STMT.Throw);
2516             this.exp = exp;
2517         }
2518 
2519         override void accept(Visitor v)
2520         {
2521             v.visit(this);
2522         }
2523     }
2524 
2525     extern (C++) class AsmStatement : Statement
2526     {
2527         Token* tokens;
2528 
2529         extern (D) this(const ref Loc loc, Token* tokens)
2530         {
2531             super(loc, STMT.Asm);
2532             this.tokens = tokens;
2533         }
2534 
2535         extern (D) this(const ref Loc loc, Token* tokens, STMT stmt)
2536         {
2537             super(loc, stmt);
2538             this.tokens = tokens;
2539         }
2540 
2541         override void accept(Visitor v)
2542         {
2543             v.visit(this);
2544         }
2545     }
2546 
2547     extern (C++) final class InlineAsmStatement : AsmStatement
2548     {
2549         extern (D) this(const ref Loc loc, Token* tokens)
2550         {
2551             super(loc, tokens, STMT.InlineAsm);
2552         }
2553 
2554         override void accept(Visitor v)
2555         {
2556             v.visit(this);
2557         }
2558     }
2559 
2560     extern (C++) final class GccAsmStatement : AsmStatement
2561     {
2562         extern (D) this(const ref Loc loc, Token* tokens)
2563         {
2564             super(loc, tokens, STMT.GccAsm);
2565         }
2566 
2567         override void accept(Visitor v)
2568         {
2569             v.visit(this);
2570         }
2571     }
2572 
2573     extern (C++) class ExpStatement : Statement
2574     {
2575         Expression exp;
2576 
2577         final extern (D) this(const ref Loc loc, Expression exp)
2578         {
2579             super(loc, STMT.Exp);
2580             this.exp = exp;
2581         }
2582         final extern (D) this(const ref Loc loc, Dsymbol declaration)
2583         {
2584             super(loc, STMT.Exp);
2585             this.exp = new DeclarationExp(loc, declaration);
2586         }
2587 
2588         override void accept(Visitor v)
2589         {
2590             v.visit(this);
2591         }
2592     }
2593 
2594     extern (C++) class CompoundStatement : Statement
2595     {
2596         Statements* statements;
2597 
2598         final extern (D) this(const ref Loc loc, Statements* statements)
2599         {
2600             super(loc, STMT.Compound);
2601             this.statements = statements;
2602         }
2603 
2604         final extern (D) this(const ref Loc loc, Statements* statements, STMT stmt)
2605         {
2606             super(loc, stmt);
2607             this.statements = statements;
2608         }
2609 
2610         final extern (D) this(const ref Loc loc, Statement[] sts...)
2611         {
2612             super(loc, STMT.Compound);
2613             statements = new Statements();
2614             statements.reserve(sts.length);
2615             foreach (s; sts)
2616                 statements.push(s);
2617         }
2618 
2619         override void accept(Visitor v)
2620         {
2621             v.visit(this);
2622         }
2623     }
2624 
2625     extern (C++) final class CompoundDeclarationStatement : CompoundStatement
2626     {
2627         final extern (D) this(const ref Loc loc, Statements* statements)
2628         {
2629             super(loc, statements, STMT.CompoundDeclaration);
2630         }
2631 
2632         override void accept(Visitor v)
2633         {
2634             v.visit(this);
2635         }
2636     }
2637 
2638     extern (C++) final class CompoundAsmStatement : CompoundStatement
2639     {
2640         StorageClass stc;
2641 
2642         final extern (D) this(const ref Loc loc, Statements* s, StorageClass stc)
2643         {
2644             super(loc, s, STMT.CompoundAsm);
2645             this.stc = stc;
2646         }
2647 
2648         override void accept(Visitor v)
2649         {
2650             v.visit(this);
2651         }
2652     }
2653 
2654     extern (C++) final class Catch : RootObject
2655     {
2656         Loc loc;
2657         Type type;
2658         Identifier ident;
2659         Statement handler;
2660 
2661         extern (D) this(const ref Loc loc, Type t, Identifier id, Statement handler)
2662         {
2663             this.loc = loc;
2664             this.type = t;
2665             this.ident = id;
2666             this.handler = handler;
2667         }
2668     }
2669 
2670     extern (C++) abstract class Type : ASTNode
2671     {
2672         TY ty;
2673         MOD mod;
2674         char* deco;
2675 
2676         extern (C++) __gshared Type tvoid;
2677         extern (C++) __gshared Type tint8;
2678         extern (C++) __gshared Type tuns8;
2679         extern (C++) __gshared Type tint16;
2680         extern (C++) __gshared Type tuns16;
2681         extern (C++) __gshared Type tint32;
2682         extern (C++) __gshared Type tuns32;
2683         extern (C++) __gshared Type tint64;
2684         extern (C++) __gshared Type tuns64;
2685         extern (C++) __gshared Type tint128;
2686         extern (C++) __gshared Type tuns128;
2687         extern (C++) __gshared Type tfloat32;
2688         extern (C++) __gshared Type tfloat64;
2689         extern (C++) __gshared Type tfloat80;
2690         extern (C++) __gshared Type timaginary32;
2691         extern (C++) __gshared Type timaginary64;
2692         extern (C++) __gshared Type timaginary80;
2693         extern (C++) __gshared Type tcomplex32;
2694         extern (C++) __gshared Type tcomplex64;
2695         extern (C++) __gshared Type tcomplex80;
2696         extern (C++) __gshared Type tbool;
2697         extern (C++) __gshared Type tchar;
2698         extern (C++) __gshared Type twchar;
2699         extern (C++) __gshared Type tdchar;
2700 
2701         extern (C++) __gshared Type[TMAX] basic;
2702 
2703         extern (C++) __gshared Type tshiftcnt;
2704         extern (C++) __gshared Type tvoidptr;    // void*
2705         extern (C++) __gshared Type tstring;     // immutable(char)[]
2706         extern (C++) __gshared Type twstring;    // immutable(wchar)[]
2707         extern (C++) __gshared Type tdstring;    // immutable(dchar)[]
2708         extern (C++) __gshared Type terror;      // for error recovery
2709         extern (C++) __gshared Type tnull;       // for null type
2710 
2711         extern (C++) __gshared Type tsize_t;     // matches size_t alias
2712         extern (C++) __gshared Type tptrdiff_t;  // matches ptrdiff_t alias
2713         extern (C++) __gshared Type thash_t;     // matches hash_t alias
2714 
2715 
2716 
2717         extern (C++) __gshared ClassDeclaration dtypeinfo;
2718         extern (C++) __gshared ClassDeclaration typeinfoclass;
2719         extern (C++) __gshared ClassDeclaration typeinfointerface;
2720         extern (C++) __gshared ClassDeclaration typeinfostruct;
2721         extern (C++) __gshared ClassDeclaration typeinfopointer;
2722         extern (C++) __gshared ClassDeclaration typeinfoarray;
2723         extern (C++) __gshared ClassDeclaration typeinfostaticarray;
2724         extern (C++) __gshared ClassDeclaration typeinfoassociativearray;
2725         extern (C++) __gshared ClassDeclaration typeinfovector;
2726         extern (C++) __gshared ClassDeclaration typeinfoenum;
2727         extern (C++) __gshared ClassDeclaration typeinfofunction;
2728         extern (C++) __gshared ClassDeclaration typeinfodelegate;
2729         extern (C++) __gshared ClassDeclaration typeinfotypelist;
2730         extern (C++) __gshared ClassDeclaration typeinfoconst;
2731         extern (C++) __gshared ClassDeclaration typeinfoinvariant;
2732         extern (C++) __gshared ClassDeclaration typeinfoshared;
2733         extern (C++) __gshared ClassDeclaration typeinfowild;
2734         extern (C++) __gshared StringTable!Type stringtable;
2735         extern (C++) __gshared ubyte[TMAX] sizeTy = ()
2736             {
2737                 ubyte[TMAX] sizeTy = __traits(classInstanceSize, TypeBasic);
2738                 sizeTy[Tsarray] = __traits(classInstanceSize, TypeSArray);
2739                 sizeTy[Tarray] = __traits(classInstanceSize, TypeDArray);
2740                 sizeTy[Taarray] = __traits(classInstanceSize, TypeAArray);
2741                 sizeTy[Tpointer] = __traits(classInstanceSize, TypePointer);
2742                 sizeTy[Treference] = __traits(classInstanceSize, TypeReference);
2743                 sizeTy[Tfunction] = __traits(classInstanceSize, TypeFunction);
2744                 sizeTy[Tdelegate] = __traits(classInstanceSize, TypeDelegate);
2745                 sizeTy[Tident] = __traits(classInstanceSize, TypeIdentifier);
2746                 sizeTy[Tinstance] = __traits(classInstanceSize, TypeInstance);
2747                 sizeTy[Ttypeof] = __traits(classInstanceSize, TypeTypeof);
2748                 sizeTy[Tenum] = __traits(classInstanceSize, TypeEnum);
2749                 sizeTy[Tstruct] = __traits(classInstanceSize, TypeStruct);
2750                 sizeTy[Tclass] = __traits(classInstanceSize, TypeClass);
2751                 sizeTy[Ttuple] = __traits(classInstanceSize, TypeTuple);
2752                 sizeTy[Tslice] = __traits(classInstanceSize, TypeSlice);
2753                 sizeTy[Treturn] = __traits(classInstanceSize, TypeReturn);
2754                 sizeTy[Terror] = __traits(classInstanceSize, TypeError);
2755                 sizeTy[Tnull] = __traits(classInstanceSize, TypeNull);
2756                 sizeTy[Tvector] = __traits(classInstanceSize, TypeVector);
2757                 sizeTy[Tmixin] = __traits(classInstanceSize, TypeMixin);
2758                 return sizeTy;
2759             }();
2760 
2761         static struct Mcache
2762         {
2763             Type cto;       // MODFlags.const_
2764             Type ito;       // MODFlags.immutable_
2765             Type sto;       // MODFlags.shared_
2766             Type scto;      // MODFlags.shared_ | MODFlags.const_
2767             Type wto;       // MODFlags.wild
2768             Type wcto;      // MODFlags.wildconst
2769             Type swto;      // MODFlags.shared_ | MODFlags.wild
2770             Type swcto;     // MODFlags.shared_ | MODFlags.wildconst
2771         }
2772         private Mcache* mcache;
2773 
2774         Type pto;
2775         Type rto;
2776         Type arrayof;
2777 
2778         // These members are probably used in semnatic analysis
2779         //TypeInfoDeclaration vtinfo;
2780         //type* ctype;
2781 
2782         final extern (D) this(TY ty)
2783         {
2784             this.ty = ty;
2785         }
2786 
2787         override const(char)* toChars() const
2788         {
2789             return "type";
2790         }
2791 
2792         static void _init()
2793         {
2794             stringtable._init(14_000);
2795 
2796             // Set basic types
2797             __gshared TY* basetab =
2798             [
2799                 Tvoid,
2800                 Tint8,
2801                 Tuns8,
2802                 Tint16,
2803                 Tuns16,
2804                 Tint32,
2805                 Tuns32,
2806                 Tint64,
2807                 Tuns64,
2808                 Tint128,
2809                 Tuns128,
2810                 Tfloat32,
2811                 Tfloat64,
2812                 Tfloat80,
2813                 Timaginary32,
2814                 Timaginary64,
2815                 Timaginary80,
2816                 Tcomplex32,
2817                 Tcomplex64,
2818                 Tcomplex80,
2819                 Tbool,
2820                 Tchar,
2821                 Twchar,
2822                 Tdchar,
2823                 Terror
2824             ];
2825 
2826             for (size_t i = 0; basetab[i] != Terror; i++)
2827             {
2828                 Type t = new TypeBasic(basetab[i]);
2829                 t = t.merge();
2830                 basic[basetab[i]] = t;
2831             }
2832             basic[Terror] = new TypeError();
2833 
2834             tvoid = basic[Tvoid];
2835             tint8 = basic[Tint8];
2836             tuns8 = basic[Tuns8];
2837             tint16 = basic[Tint16];
2838             tuns16 = basic[Tuns16];
2839             tint32 = basic[Tint32];
2840             tuns32 = basic[Tuns32];
2841             tint64 = basic[Tint64];
2842             tuns64 = basic[Tuns64];
2843             tint128 = basic[Tint128];
2844             tuns128 = basic[Tuns128];
2845             tfloat32 = basic[Tfloat32];
2846             tfloat64 = basic[Tfloat64];
2847             tfloat80 = basic[Tfloat80];
2848 
2849             timaginary32 = basic[Timaginary32];
2850             timaginary64 = basic[Timaginary64];
2851             timaginary80 = basic[Timaginary80];
2852 
2853             tcomplex32 = basic[Tcomplex32];
2854             tcomplex64 = basic[Tcomplex64];
2855             tcomplex80 = basic[Tcomplex80];
2856 
2857             tbool = basic[Tbool];
2858             tchar = basic[Tchar];
2859             twchar = basic[Twchar];
2860             tdchar = basic[Tdchar];
2861 
2862             tshiftcnt = tint32;
2863             terror = basic[Terror];
2864             tnull = new TypeNull();
2865             tnull.deco = tnull.merge().deco;
2866 
2867             tvoidptr = tvoid.pointerTo();
2868             tstring = tchar.immutableOf().arrayOf();
2869             twstring = twchar.immutableOf().arrayOf();
2870             tdstring = tdchar.immutableOf().arrayOf();
2871 
2872             const isLP64 = global.params.isLP64;
2873 
2874             tsize_t    = basic[isLP64 ? Tuns64 : Tuns32];
2875             tptrdiff_t = basic[isLP64 ? Tint64 : Tint32];
2876             thash_t = tsize_t;
2877         }
2878 
2879         extern (D)
2880         final Mcache* getMcache()
2881         {
2882             if (!mcache)
2883                 mcache = cast(Mcache*) mem.xcalloc(Mcache.sizeof, 1);
2884             return mcache;
2885         }
2886 
2887         final Type pointerTo()
2888         {
2889             if (ty == Terror)
2890                 return this;
2891             if (!pto)
2892             {
2893                 Type t = new TypePointer(this);
2894                 if (ty == Tfunction)
2895                 {
2896                     t.deco = t.merge().deco;
2897                     pto = t;
2898                 }
2899                 else
2900                     pto = t.merge();
2901             }
2902             return pto;
2903         }
2904 
2905         final Type arrayOf()
2906         {
2907             if (ty == Terror)
2908                 return this;
2909             if (!arrayof)
2910             {
2911                 Type t = new TypeDArray(this);
2912                 arrayof = t.merge();
2913             }
2914             return arrayof;
2915         }
2916 
2917         final bool isImmutable() const
2918         {
2919             return (mod & MODFlags.immutable_) != 0;
2920         }
2921 
2922         final Type nullAttributes()
2923         {
2924             uint sz = sizeTy[ty];
2925             Type t = cast(Type)mem.xmalloc(sz);
2926             memcpy(cast(void*)t, cast(void*)this, sz);
2927             // t.mod = NULL;  // leave mod unchanged
2928             t.deco = null;
2929             t.arrayof = null;
2930             t.pto = null;
2931             t.rto = null;
2932             t.mcache = null;
2933             //t.vtinfo = null; these aren't used in parsing
2934             //t.ctype = null;
2935             if (t.ty == Tstruct)
2936                 (cast(TypeStruct)t).att = AliasThisRec.fwdref;
2937             if (t.ty == Tclass)
2938                 (cast(TypeClass)t).att = AliasThisRec.fwdref;
2939             return t;
2940         }
2941 
2942         Type makeConst()
2943         {
2944             if (mcache && mcache.cto)
2945                 return mcache.cto;
2946             Type t = this.nullAttributes();
2947             t.mod = MODFlags.const_;
2948             return t;
2949         }
2950 
2951         Type makeWildConst()
2952         {
2953             if (mcache && mcache.wcto)
2954                 return mcache.wcto;
2955             Type t = this.nullAttributes();
2956             t.mod = MODFlags.wildconst;
2957             return t;
2958         }
2959 
2960         Type makeShared()
2961         {
2962             if (mcache && mcache.sto)
2963                 return mcache.sto;
2964             Type t = this.nullAttributes();
2965             t.mod = MODFlags.shared_;
2966             return t;
2967         }
2968 
2969         Type makeSharedConst()
2970         {
2971             if (mcache && mcache.scto)
2972                 return mcache.scto;
2973             Type t = this.nullAttributes();
2974             t.mod = MODFlags.shared_ | MODFlags.const_;
2975             return t;
2976         }
2977 
2978         Type makeImmutable()
2979         {
2980             if (mcache && mcache.ito)
2981                 return mcache.ito;
2982             Type t = this.nullAttributes();
2983             t.mod = MODFlags.immutable_;
2984             return t;
2985         }
2986 
2987         Type makeWild()
2988         {
2989             if (mcache && mcache.wto)
2990                 return mcache.wto;
2991             Type t = this.nullAttributes();
2992             t.mod = MODFlags.wild;
2993             return t;
2994         }
2995 
2996         Type makeSharedWildConst()
2997         {
2998             if (mcache && mcache.swcto)
2999                 return mcache.swcto;
3000             Type t = this.nullAttributes();
3001             t.mod = MODFlags.shared_ | MODFlags.wildconst;
3002             return t;
3003         }
3004 
3005         Type makeSharedWild()
3006         {
3007             if (mcache && mcache.swto)
3008                 return mcache.swto;
3009             Type t = this.nullAttributes();
3010             t.mod = MODFlags.shared_ | MODFlags.wild;
3011             return t;
3012         }
3013 
3014         // Truncated
3015         final Type merge()
3016         {
3017             if (ty == Terror)
3018                 return this;
3019             if (ty == Ttypeof)
3020                 return this;
3021             if (ty == Tident)
3022                 return this;
3023             if (ty == Tinstance)
3024                 return this;
3025             if (ty == Taarray && !(cast(TypeAArray)this).index.merge().deco)
3026                 return this;
3027             if (ty != Tenum && nextOf() && !nextOf().deco)
3028                 return this;
3029 
3030             // if (!deco) - code missing
3031 
3032             Type t = this;
3033             assert(t);
3034             return t;
3035         }
3036 
3037         final Type addSTC(StorageClass stc)
3038         {
3039             Type t = this;
3040             if (t.isImmutable())
3041             {
3042             }
3043             else if (stc & STC.immutable_)
3044             {
3045                 t = t.makeImmutable();
3046             }
3047             else
3048             {
3049                 if ((stc & STC.shared_) && !t.isShared())
3050                 {
3051                     if (t.isWild())
3052                     {
3053                         if (t.isConst())
3054                             t = t.makeSharedWildConst();
3055                         else
3056                             t = t.makeSharedWild();
3057                     }
3058                     else
3059                     {
3060                         if (t.isConst())
3061                             t = t.makeSharedConst();
3062                         else
3063                             t = t.makeShared();
3064                     }
3065                 }
3066                 if ((stc & STC.const_) && !t.isConst())
3067                 {
3068                     if (t.isShared())
3069                     {
3070                         if (t.isWild())
3071                             t = t.makeSharedWildConst();
3072                         else
3073                             t = t.makeSharedConst();
3074                     }
3075                     else
3076                     {
3077                         if (t.isWild())
3078                             t = t.makeWildConst();
3079                         else
3080                             t = t.makeConst();
3081                     }
3082                 }
3083                 if ((stc & STC.wild) && !t.isWild())
3084                 {
3085                     if (t.isShared())
3086                     {
3087                         if (t.isConst())
3088                             t = t.makeSharedWildConst();
3089                         else
3090                             t = t.makeSharedWild();
3091                     }
3092                     else
3093                     {
3094                         if (t.isConst())
3095                             t = t.makeWildConst();
3096                         else
3097                             t = t.makeWild();
3098                     }
3099                 }
3100             }
3101             return t;
3102         }
3103 
3104         Expression toExpression()
3105         {
3106             return null;
3107         }
3108 
3109         Type syntaxCopy()
3110         {
3111             return null;
3112         }
3113 
3114         final Type sharedWildConstOf()
3115         {
3116             if (mod == (MODFlags.shared_ | MODFlags.wildconst))
3117                 return this;
3118             if (mcache.swcto)
3119             {
3120                 assert(mcache.swcto.mod == (MODFlags.shared_ | MODFlags.wildconst));
3121                 return mcache.swcto;
3122             }
3123             Type t = makeSharedWildConst();
3124             t = t.merge();
3125             t.fixTo(this);
3126             return t;
3127         }
3128 
3129         final Type sharedConstOf()
3130         {
3131             if (mod == (MODFlags.shared_ | MODFlags.const_))
3132                 return this;
3133             if (mcache.scto)
3134             {
3135                 assert(mcache.scto.mod == (MODFlags.shared_ | MODFlags.const_));
3136                 return mcache.scto;
3137             }
3138             Type t = makeSharedConst();
3139             t = t.merge();
3140             t.fixTo(this);
3141             return t;
3142         }
3143 
3144         final Type wildConstOf()
3145         {
3146             if (mod == MODFlags.wildconst)
3147                 return this;
3148             if (mcache && mcache.wcto)
3149             {
3150                 assert(mcache.wcto.mod == MODFlags.wildconst);
3151                 return mcache.wcto;
3152             }
3153             Type t = makeWildConst();
3154             t = t.merge();
3155             t.fixTo(this);
3156             return t;
3157         }
3158 
3159         final Type constOf()
3160         {
3161             if (mod == MODFlags.const_)
3162                 return this;
3163             if (mcache && mcache.cto)
3164             {
3165                 assert(mcache.cto.mod == MODFlags.const_);
3166                 return mcache.cto;
3167             }
3168             Type t = makeConst();
3169             t = t.merge();
3170             t.fixTo(this);
3171             return t;
3172         }
3173 
3174         final Type sharedWildOf()
3175         {
3176             if (mod == (MODFlags.shared_ | MODFlags.wild))
3177                 return this;
3178             if (mcache && mcache.swto)
3179             {
3180                 assert(mcache.swto.mod == (MODFlags.shared_ | MODFlags.wild));
3181                 return mcache.swto;
3182             }
3183             Type t = makeSharedWild();
3184             t = t.merge();
3185             t.fixTo(this);
3186             return t;
3187         }
3188 
3189         final Type wildOf()
3190         {
3191             if (mod == MODFlags.wild)
3192                 return this;
3193             if (mcache && mcache.wto)
3194             {
3195                 assert(mcache.wto.mod == MODFlags.wild);
3196                 return mcache.wto;
3197             }
3198             Type t = makeWild();
3199             t = t.merge();
3200             t.fixTo(this);
3201             return t;
3202         }
3203 
3204         final Type sharedOf()
3205         {
3206             if (mod == MODFlags.shared_)
3207                 return this;
3208             if (mcache && mcache.sto)
3209             {
3210                 assert(mcache.sto.mod == MODFlags.shared_);
3211                 return mcache.sto;
3212             }
3213             Type t = makeShared();
3214             t = t.merge();
3215             t.fixTo(this);
3216             return t;
3217         }
3218 
3219         final Type immutableOf()
3220         {
3221             if (isImmutable())
3222                 return this;
3223             if (mcache && mcache.ito)
3224             {
3225                 assert(mcache.ito.isImmutable());
3226                 return mcache.ito;
3227             }
3228             Type t = makeImmutable();
3229             t = t.merge();
3230             t.fixTo(this);
3231             return t;
3232         }
3233 
3234         final void fixTo(Type t)
3235         {
3236             Type mto = null;
3237             Type tn = nextOf();
3238             if (!tn || ty != Tsarray && tn.mod == t.nextOf().mod)
3239             {
3240                 switch (t.mod)
3241                 {
3242                 case 0:
3243                     mto = t;
3244                     break;
3245 
3246                 case MODFlags.const_:
3247                     getMcache();
3248                     mcache.cto = t;
3249                     break;
3250 
3251                 case MODFlags.wild:
3252                     getMcache();
3253                     mcache.wto = t;
3254                     break;
3255 
3256                 case MODFlags.wildconst:
3257                     getMcache();
3258                     mcache.wcto = t;
3259                     break;
3260 
3261                 case MODFlags.shared_:
3262                     getMcache();
3263                     mcache.sto = t;
3264                     break;
3265 
3266                 case MODFlags.shared_ | MODFlags.const_:
3267                     getMcache();
3268                     mcache.scto = t;
3269                     break;
3270 
3271                 case MODFlags.shared_ | MODFlags.wild:
3272                     getMcache();
3273                     mcache.swto = t;
3274                     break;
3275 
3276                 case MODFlags.shared_ | MODFlags.wildconst:
3277                     getMcache();
3278                     mcache.swcto = t;
3279                     break;
3280 
3281                 case MODFlags.immutable_:
3282                     getMcache();
3283                     mcache.ito = t;
3284                     break;
3285 
3286                 default:
3287                     break;
3288                 }
3289             }
3290             assert(mod != t.mod);
3291 
3292             if (mod)
3293             {
3294                 getMcache();
3295                 t.getMcache();
3296             }
3297             switch (mod)
3298             {
3299             case 0:
3300                 break;
3301 
3302             case MODFlags.const_:
3303                 mcache.cto = mto;
3304                 t.mcache.cto = this;
3305                 break;
3306 
3307             case MODFlags.wild:
3308                 mcache.wto = mto;
3309                 t.mcache.wto = this;
3310                 break;
3311 
3312             case MODFlags.wildconst:
3313                 mcache.wcto = mto;
3314                 t.mcache.wcto = this;
3315                 break;
3316 
3317             case MODFlags.shared_:
3318                 mcache.sto = mto;
3319                 t.mcache.sto = this;
3320                 break;
3321 
3322             case MODFlags.shared_ | MODFlags.const_:
3323                 mcache.scto = mto;
3324                 t.mcache.scto = this;
3325                 break;
3326 
3327             case MODFlags.shared_ | MODFlags.wild:
3328                 mcache.swto = mto;
3329                 t.mcache.swto = this;
3330                 break;
3331 
3332             case MODFlags.shared_ | MODFlags.wildconst:
3333                 mcache.swcto = mto;
3334                 t.mcache.swcto = this;
3335                 break;
3336 
3337             case MODFlags.immutable_:
3338                 t.mcache.ito = this;
3339                 if (t.mcache.cto)
3340                     t.mcache.cto.getMcache().ito = this;
3341                 if (t.mcache.sto)
3342                     t.mcache.sto.getMcache().ito = this;
3343                 if (t.mcache.scto)
3344                     t.mcache.scto.getMcache().ito = this;
3345                 if (t.mcache.wto)
3346                     t.mcache.wto.getMcache().ito = this;
3347                 if (t.mcache.wcto)
3348                     t.mcache.wcto.getMcache().ito = this;
3349                 if (t.mcache.swto)
3350                     t.mcache.swto.getMcache().ito = this;
3351                 if (t.mcache.swcto)
3352                     t.mcache.swcto.getMcache().ito = this;
3353                 break;
3354 
3355             default:
3356                 assert(0);
3357             }
3358         }
3359 
3360         final Type addMod(MOD mod)
3361         {
3362             Type t = this;
3363             if (!t.isImmutable())
3364             {
3365                 switch (mod)
3366                 {
3367                 case 0:
3368                     break;
3369 
3370                 case MODFlags.const_:
3371                     if (isShared())
3372                     {
3373                         if (isWild())
3374                             t = sharedWildConstOf();
3375                         else
3376                             t = sharedConstOf();
3377                     }
3378                     else
3379                     {
3380                         if (isWild())
3381                             t = wildConstOf();
3382                         else
3383                             t = constOf();
3384                     }
3385                     break;
3386 
3387                 case MODFlags.wild:
3388                     if (isShared())
3389                     {
3390                         if (isConst())
3391                             t = sharedWildConstOf();
3392                         else
3393                             t = sharedWildOf();
3394                     }
3395                     else
3396                     {
3397                         if (isConst())
3398                             t = wildConstOf();
3399                         else
3400                             t = wildOf();
3401                     }
3402                     break;
3403 
3404                 case MODFlags.wildconst:
3405                     if (isShared())
3406                         t = sharedWildConstOf();
3407                     else
3408                         t = wildConstOf();
3409                     break;
3410 
3411                 case MODFlags.shared_:
3412                     if (isWild())
3413                     {
3414                         if (isConst())
3415                             t = sharedWildConstOf();
3416                         else
3417                             t = sharedWildOf();
3418                     }
3419                     else
3420                     {
3421                         if (isConst())
3422                             t = sharedConstOf();
3423                         else
3424                             t = sharedOf();
3425                     }
3426                     break;
3427 
3428                 case MODFlags.shared_ | MODFlags.const_:
3429                     if (isWild())
3430                         t = sharedWildConstOf();
3431                     else
3432                         t = sharedConstOf();
3433                     break;
3434 
3435                 case MODFlags.shared_ | MODFlags.wild:
3436                     if (isConst())
3437                         t = sharedWildConstOf();
3438                     else
3439                         t = sharedWildOf();
3440                     break;
3441 
3442                 case MODFlags.shared_ | MODFlags.wildconst:
3443                     t = sharedWildConstOf();
3444                     break;
3445 
3446                 case MODFlags.immutable_:
3447                     t = immutableOf();
3448                     break;
3449 
3450                 default:
3451                     assert(0);
3452                 }
3453             }
3454             return t;
3455         }
3456 
3457         // TypeEnum overrides this method
3458         Type nextOf()
3459         {
3460             return null;
3461         }
3462 
3463         // TypeBasic, TypeVector, TypePointer, TypeEnum override this method
3464         bool isscalar()
3465         {
3466             return false;
3467         }
3468 
3469         final bool isConst() const
3470         {
3471             return (mod & MODFlags.const_) != 0;
3472         }
3473 
3474         final bool isWild() const
3475         {
3476             return (mod & MODFlags.wild) != 0;
3477         }
3478 
3479         final bool isShared() const
3480         {
3481             return (mod & MODFlags.shared_) != 0;
3482         }
3483 
3484         Type toBasetype()
3485         {
3486             return this;
3487         }
3488 
3489         // TypeIdentifier, TypeInstance, TypeTypeOf, TypeReturn, TypeStruct, TypeEnum, TypeClass override this method
3490         Dsymbol toDsymbol(Scope* sc)
3491         {
3492             return null;
3493         }
3494 
3495         final pure inout nothrow @nogc
3496         {
3497             inout(TypeError)      isTypeError()      { return ty == Terror     ? cast(typeof(return))this : null; }
3498             inout(TypeVector)     isTypeVector()     { return ty == Tvector    ? cast(typeof(return))this : null; }
3499             inout(TypeSArray)     isTypeSArray()     { return ty == Tsarray    ? cast(typeof(return))this : null; }
3500             inout(TypeDArray)     isTypeDArray()     { return ty == Tarray     ? cast(typeof(return))this : null; }
3501             inout(TypeAArray)     isTypeAArray()     { return ty == Taarray    ? cast(typeof(return))this : null; }
3502             inout(TypePointer)    isTypePointer()    { return ty == Tpointer   ? cast(typeof(return))this : null; }
3503             inout(TypeReference)  isTypeReference()  { return ty == Treference ? cast(typeof(return))this : null; }
3504             inout(TypeFunction)   isTypeFunction()   { return ty == Tfunction  ? cast(typeof(return))this : null; }
3505             inout(TypeDelegate)   isTypeDelegate()   { return ty == Tdelegate  ? cast(typeof(return))this : null; }
3506             inout(TypeIdentifier) isTypeIdentifier() { return ty == Tident     ? cast(typeof(return))this : null; }
3507             inout(TypeInstance)   isTypeInstance()   { return ty == Tinstance  ? cast(typeof(return))this : null; }
3508             inout(TypeTypeof)     isTypeTypeof()     { return ty == Ttypeof    ? cast(typeof(return))this : null; }
3509             inout(TypeReturn)     isTypeReturn()     { return ty == Treturn    ? cast(typeof(return))this : null; }
3510             inout(TypeStruct)     isTypeStruct()     { return ty == Tstruct    ? cast(typeof(return))this : null; }
3511             inout(TypeEnum)       isTypeEnum()       { return ty == Tenum      ? cast(typeof(return))this : null; }
3512             inout(TypeClass)      isTypeClass()      { return ty == Tclass     ? cast(typeof(return))this : null; }
3513             inout(TypeTuple)      isTypeTuple()      { return ty == Ttuple     ? cast(typeof(return))this : null; }
3514             inout(TypeSlice)      isTypeSlice()      { return ty == Tslice     ? cast(typeof(return))this : null; }
3515             inout(TypeNull)       isTypeNull()       { return ty == Tnull      ? cast(typeof(return))this : null; }
3516             inout(TypeMixin)      isTypeMixin()      { return ty == Tmixin     ? cast(typeof(return))this : null; }
3517             inout(TypeTraits)     isTypeTraits()     { return ty == Ttraits    ? cast(typeof(return))this : null; }
3518         }
3519 
3520         override void accept(Visitor v)
3521         {
3522             v.visit(this);
3523         }
3524     }
3525 
3526     // missing functionality in constructor, but that's ok
3527     // since the class is needed only for its size; need to add all method definitions
3528     extern (C++) final class TypeBasic : Type
3529     {
3530         const(char)* dstring;
3531         uint flags;
3532 
3533         extern (D) this(TY ty)
3534         {
3535             super(ty);
3536             const(char)* d;
3537             uint flags = 0;
3538             switch (ty)
3539             {
3540             case Tvoid:
3541                 d = Token.toChars(TOK.void_);
3542                 break;
3543 
3544             case Tint8:
3545                 d = Token.toChars(TOK.int8);
3546                 flags |= TFlags.integral;
3547                 break;
3548 
3549             case Tuns8:
3550                 d = Token.toChars(TOK.uns8);
3551                 flags |= TFlags.integral | TFlags.unsigned;
3552                 break;
3553 
3554             case Tint16:
3555                 d = Token.toChars(TOK.int16);
3556                 flags |= TFlags.integral;
3557                 break;
3558 
3559             case Tuns16:
3560                 d = Token.toChars(TOK.uns16);
3561                 flags |= TFlags.integral | TFlags.unsigned;
3562                 break;
3563 
3564             case Tint32:
3565                 d = Token.toChars(TOK.int32);
3566                 flags |= TFlags.integral;
3567                 break;
3568 
3569             case Tuns32:
3570                 d = Token.toChars(TOK.uns32);
3571                 flags |= TFlags.integral | TFlags.unsigned;
3572                 break;
3573 
3574             case Tfloat32:
3575                 d = Token.toChars(TOK.float32);
3576                 flags |= TFlags.floating | TFlags.real_;
3577                 break;
3578 
3579             case Tint64:
3580                 d = Token.toChars(TOK.int64);
3581                 flags |= TFlags.integral;
3582                 break;
3583 
3584             case Tuns64:
3585                 d = Token.toChars(TOK.uns64);
3586                 flags |= TFlags.integral | TFlags.unsigned;
3587                 break;
3588 
3589             case Tint128:
3590                 d = Token.toChars(TOK.int128);
3591                 flags |= TFlags.integral;
3592                 break;
3593 
3594             case Tuns128:
3595                 d = Token.toChars(TOK.uns128);
3596                 flags |= TFlags.integral | TFlags.unsigned;
3597                 break;
3598 
3599             case Tfloat64:
3600                 d = Token.toChars(TOK.float64);
3601                 flags |= TFlags.floating | TFlags.real_;
3602                 break;
3603 
3604             case Tfloat80:
3605                 d = Token.toChars(TOK.float80);
3606                 flags |= TFlags.floating | TFlags.real_;
3607                 break;
3608 
3609             case Timaginary32:
3610                 d = Token.toChars(TOK.imaginary32);
3611                 flags |= TFlags.floating | TFlags.imaginary;
3612                 break;
3613 
3614             case Timaginary64:
3615                 d = Token.toChars(TOK.imaginary64);
3616                 flags |= TFlags.floating | TFlags.imaginary;
3617                 break;
3618 
3619             case Timaginary80:
3620                 d = Token.toChars(TOK.imaginary80);
3621                 flags |= TFlags.floating | TFlags.imaginary;
3622                 break;
3623 
3624             case Tcomplex32:
3625                 d = Token.toChars(TOK.complex32);
3626                 flags |= TFlags.floating | TFlags.complex;
3627                 break;
3628 
3629             case Tcomplex64:
3630                 d = Token.toChars(TOK.complex64);
3631                 flags |= TFlags.floating | TFlags.complex;
3632                 break;
3633 
3634             case Tcomplex80:
3635                 d = Token.toChars(TOK.complex80);
3636                 flags |= TFlags.floating | TFlags.complex;
3637                 break;
3638 
3639             case Tbool:
3640                 d = "bool";
3641                 flags |= TFlags.integral | TFlags.unsigned;
3642                 break;
3643 
3644             case Tchar:
3645                 d = Token.toChars(TOK.char_);
3646                 flags |= TFlags.integral | TFlags.unsigned;
3647                 break;
3648 
3649             case Twchar:
3650                 d = Token.toChars(TOK.wchar_);
3651                 flags |= TFlags.integral | TFlags.unsigned;
3652                 break;
3653 
3654             case Tdchar:
3655                 d = Token.toChars(TOK.dchar_);
3656                 flags |= TFlags.integral | TFlags.unsigned;
3657                 break;
3658 
3659             default:
3660                 assert(0);
3661             }
3662             this.dstring = d;
3663             this.flags = flags;
3664             merge();
3665         }
3666 
3667         override bool isscalar() const
3668         {
3669             return (flags & (TFlags.integral | TFlags.floating)) != 0;
3670         }
3671 
3672         override void accept(Visitor v)
3673         {
3674             v.visit(this);
3675         }
3676     }
3677 
3678     extern (C++) final class TypeError : Type
3679     {
3680         extern (D) this()
3681         {
3682             super(Terror);
3683         }
3684 
3685         override Type syntaxCopy()
3686         {
3687             return this;
3688         }
3689 
3690         override void accept(Visitor v)
3691         {
3692             v.visit(this);
3693         }
3694     }
3695 
3696     extern (C++) final class TypeNull : Type
3697     {
3698         extern (D) this()
3699         {
3700             super(Tnull);
3701         }
3702 
3703         override Type syntaxCopy()
3704         {
3705             // No semantic analysis done, no need to copy
3706             return this;
3707         }
3708 
3709         override void accept(Visitor v)
3710         {
3711             v.visit(this);
3712         }
3713     }
3714 
3715     extern (C++) class TypeVector : Type
3716     {
3717         Type basetype;
3718 
3719         extern (D) this(Type basetype)
3720         {
3721             super(Tvector);
3722             this.basetype = basetype;
3723         }
3724 
3725         override Type syntaxCopy()
3726         {
3727             return new TypeVector(basetype.syntaxCopy());
3728         }
3729 
3730         override void accept(Visitor v)
3731         {
3732             v.visit(this);
3733         }
3734     }
3735 
3736     extern (C++) final class TypeEnum : Type
3737     {
3738         EnumDeclaration sym;
3739 
3740         extern (D) this(EnumDeclaration sym)
3741         {
3742             super(Tenum);
3743             this.sym = sym;
3744         }
3745 
3746         override Type syntaxCopy()
3747         {
3748             return this;
3749         }
3750 
3751         override void accept(Visitor v)
3752         {
3753             v.visit(this);
3754         }
3755     }
3756 
3757     extern (C++) final class TypeTuple : Type
3758     {
3759         Parameters* arguments;
3760 
3761         extern (D) this(Parameters* arguments)
3762         {
3763             super(Ttuple);
3764             this.arguments = arguments;
3765         }
3766 
3767         extern (D) this(Expressions* exps)
3768         {
3769             super(Ttuple);
3770             auto arguments = new Parameters();
3771             if (exps)
3772             {
3773                 arguments.setDim(exps.dim);
3774                 for (size_t i = 0; i < exps.dim; i++)
3775                 {
3776                     Expression e = (*exps)[i];
3777                     if (e.type.ty == Ttuple)
3778                         e.error("cannot form tuple of tuples");
3779                     auto arg = new Parameter(STC.undefined_, e.type, null, null, null);
3780                     (*arguments)[i] = arg;
3781                 }
3782             }
3783             this.arguments = arguments;
3784         }
3785 
3786         override Type syntaxCopy()
3787         {
3788             Parameters* args = Parameter.arraySyntaxCopy(arguments);
3789             Type t = new TypeTuple(args);
3790             t.mod = mod;
3791             return t;
3792         }
3793 
3794         override void accept(Visitor v)
3795         {
3796             v.visit(this);
3797         }
3798     }
3799 
3800     extern (C++) final class TypeClass : Type
3801     {
3802         ClassDeclaration sym;
3803         AliasThisRec att = AliasThisRec.fwdref;
3804 
3805         extern (D) this (ClassDeclaration sym)
3806         {
3807             super(Tclass);
3808             this.sym = sym;
3809         }
3810 
3811         override Type syntaxCopy()
3812         {
3813             return this;
3814         }
3815 
3816         override void accept(Visitor v)
3817         {
3818             v.visit(this);
3819         }
3820     }
3821 
3822     extern (C++) final class TypeStruct : Type
3823     {
3824         StructDeclaration sym;
3825         AliasThisRec att = AliasThisRec.fwdref;
3826         bool inuse = false;
3827 
3828         extern (D) this(StructDeclaration sym)
3829         {
3830             super(Tstruct);
3831             this.sym = sym;
3832         }
3833 
3834         override Type syntaxCopy()
3835         {
3836             return this;
3837         }
3838 
3839         override void accept(Visitor v)
3840         {
3841             v.visit(this);
3842         }
3843     }
3844 
3845     extern (C++) final class TypeReference : TypeNext
3846     {
3847         extern (D) this(Type t)
3848         {
3849             super(Treference, t);
3850             // BUG: what about references to static arrays?
3851         }
3852 
3853         override Type syntaxCopy()
3854         {
3855             Type t = next.syntaxCopy();
3856             if (t == next)
3857                 t = this;
3858             else
3859             {
3860                 t = new TypeReference(t);
3861                 t.mod = mod;
3862             }
3863             return t;
3864         }
3865 
3866         override void accept(Visitor v)
3867         {
3868             v.visit(this);
3869         }
3870     }
3871 
3872     extern (C++) abstract class TypeNext : Type
3873     {
3874         Type next;
3875 
3876         final extern (D) this(TY ty, Type next)
3877         {
3878             super(ty);
3879             this.next = next;
3880         }
3881 
3882         override final Type nextOf()
3883         {
3884             return next;
3885         }
3886 
3887         override void accept(Visitor v)
3888         {
3889             v.visit(this);
3890         }
3891     }
3892 
3893     extern (C++) final class TypeSlice : TypeNext
3894     {
3895         Expression lwr;
3896         Expression upr;
3897 
3898         extern (D) this(Type next, Expression lwr, Expression upr)
3899         {
3900             super(Tslice, next);
3901             this.lwr = lwr;
3902             this.upr = upr;
3903         }
3904 
3905         override Type syntaxCopy()
3906         {
3907             Type t = new TypeSlice(next.syntaxCopy(), lwr.syntaxCopy(), upr.syntaxCopy());
3908             t.mod = mod;
3909             return t;
3910         }
3911 
3912         override void accept(Visitor v)
3913         {
3914             v.visit(this);
3915         }
3916     }
3917 
3918     extern (C++) class TypeDelegate : TypeNext
3919     {
3920         extern (D) this(Type t)
3921         {
3922             super(Tfunction, t);
3923             ty = Tdelegate;
3924         }
3925 
3926         override Type syntaxCopy()
3927         {
3928             Type t = next.syntaxCopy();
3929             if (t == next)
3930                 t = this;
3931             else
3932             {
3933                 t = new TypeDelegate(t);
3934                 t.mod = mod;
3935             }
3936             return t;
3937         }
3938 
3939         override void accept(Visitor v)
3940         {
3941             v.visit(this);
3942         }
3943     }
3944 
3945     extern (C++) final class TypePointer : TypeNext
3946     {
3947         extern (D) this(Type t)
3948         {
3949             super(Tpointer, t);
3950         }
3951 
3952         override Type syntaxCopy()
3953         {
3954             Type t = next.syntaxCopy();
3955             if (t == next)
3956                 t = this;
3957             else
3958             {
3959                 t = new TypePointer(t);
3960                 t.mod = mod;
3961             }
3962             return t;
3963         }
3964 
3965         override void accept(Visitor v)
3966         {
3967             v.visit(this);
3968         }
3969     }
3970 
3971     extern (C++) class TypeFunction : TypeNext
3972     {
3973         // .next is the return type
3974 
3975         ParameterList parameterList;   // function parameters
3976 
3977         private enum FunctionFlag : uint
3978         {
3979             none            = 0,
3980             isnothrow       = 0x0001, // nothrow
3981             isnogc          = 0x0002, // is @nogc
3982             isproperty      = 0x0004, // can be called without parentheses
3983             isref           = 0x0008, // returns a reference
3984             isreturn        = 0x0010, // 'this' is returned by ref
3985             isscope         = 0x0020, // 'this' is scope
3986             isreturninferred= 0x0040, // 'this' is return from inference
3987             isscopeinferred = 0x0080, // 'this' is scope from inference
3988             islive          = 0x0100, // is @live
3989             incomplete      = 0x0200, // return type or default arguments removed
3990             inoutParam      = 0x0400, // inout on the parameters
3991             inoutQual       = 0x0800, // inout on the qualifier
3992         }
3993 
3994         LINK linkage;               // calling convention
3995         FunctionFlag funcFlags;
3996         TRUST trust;                // level of trust
3997         PURE purity = PURE.impure;
3998         byte inuse;
3999         Expressions* fargs;         // function arguments
4000 
4001         extern (D) this(ParameterList pl, Type treturn, LINK linkage, StorageClass stc = 0)
4002         {
4003             super(Tfunction, treturn);
4004             assert(VarArg.none <= pl.varargs && pl.varargs <= VarArg.typesafe);
4005             this.parameterList = pl;
4006             this.linkage = linkage;
4007 
4008             if (stc & STC.pure_)
4009                 this.purity = PURE.fwdref;
4010             if (stc & STC.nothrow_)
4011                 this.isnothrow = true;
4012             if (stc & STC.nogc)
4013                 this.isnogc = true;
4014             if (stc & STC.property)
4015                 this.isproperty = true;
4016             if (stc & STC.live)
4017                 this.islive = true;
4018 
4019             if (stc & STC.ref_)
4020                 this.isref = true;
4021             if (stc & STC.return_)
4022                 this.isreturn = true;
4023             if (stc & STC.scope_)
4024                 this.isScopeQual = true;
4025 
4026             this.trust = TRUST.default_;
4027             if (stc & STC.safe)
4028                 this.trust = TRUST.safe;
4029             if (stc & STC.system)
4030                 this.trust = TRUST.system;
4031             if (stc & STC.trusted)
4032                 this.trust = TRUST.trusted;
4033         }
4034 
4035         override Type syntaxCopy()
4036         {
4037             Type treturn = next ? next.syntaxCopy() : null;
4038             Parameters* params = Parameter.arraySyntaxCopy(parameterList.parameters);
4039             auto t = new TypeFunction(ParameterList(params, parameterList.varargs), treturn, linkage);
4040             t.mod = mod;
4041             t.isnothrow = isnothrow;
4042             t.isnogc = isnogc;
4043             t.purity = purity;
4044             t.isproperty = isproperty;
4045             t.isref = isref;
4046             t.isreturn = isreturn;
4047             t.isScopeQual = isScopeQual;
4048             t.isreturninferred = isreturninferred;
4049             t.isscopeinferred = isscopeinferred;
4050             t.isInOutParam = isInOutParam;
4051             t.isInOutQual = isInOutQual;
4052             t.trust = trust;
4053             t.fargs = fargs;
4054             return t;
4055         }
4056 
4057         /// set or get if the function has the `nothrow` attribute
4058         bool isnothrow() const pure nothrow @safe @nogc
4059         {
4060             return (funcFlags & FunctionFlag.isnothrow) != 0;
4061         }
4062         /// ditto
4063         void isnothrow(bool v) pure nothrow @safe @nogc
4064         {
4065             if (v) funcFlags |= FunctionFlag.isnothrow;
4066             else funcFlags &= ~FunctionFlag.isnothrow;
4067         }
4068 
4069         /// set or get if the function has the `@nogc` attribute
4070         bool isnogc() const pure nothrow @safe @nogc
4071         {
4072             return (funcFlags & FunctionFlag.isnogc) != 0;
4073         }
4074         /// ditto
4075         void isnogc(bool v) pure nothrow @safe @nogc
4076         {
4077             if (v) funcFlags |= FunctionFlag.isnogc;
4078             else funcFlags &= ~FunctionFlag.isnogc;
4079         }
4080 
4081         /// set or get if the function has the `@property` attribute
4082         bool isproperty() const pure nothrow @safe @nogc
4083         {
4084             return (funcFlags & FunctionFlag.isproperty) != 0;
4085         }
4086         /// ditto
4087         void isproperty(bool v) pure nothrow @safe @nogc
4088         {
4089             if (v) funcFlags |= FunctionFlag.isproperty;
4090             else funcFlags &= ~FunctionFlag.isproperty;
4091         }
4092 
4093         /// set or get if the function has the `ref` attribute
4094         bool isref() const pure nothrow @safe @nogc
4095         {
4096             return (funcFlags & FunctionFlag.isref) != 0;
4097         }
4098         /// ditto
4099         void isref(bool v) pure nothrow @safe @nogc
4100         {
4101             if (v) funcFlags |= FunctionFlag.isref;
4102             else funcFlags &= ~FunctionFlag.isref;
4103         }
4104 
4105         /// set or get if the function has the `return` attribute
4106         bool isreturn() const pure nothrow @safe @nogc
4107         {
4108             return (funcFlags & FunctionFlag.isreturn) != 0;
4109         }
4110         /// ditto
4111         void isreturn(bool v) pure nothrow @safe @nogc
4112         {
4113             if (v) funcFlags |= FunctionFlag.isreturn;
4114             else funcFlags &= ~FunctionFlag.isreturn;
4115         }
4116 
4117         /// set or get if the function has the `scope` attribute
4118         bool isScopeQual() const pure nothrow @safe @nogc
4119         {
4120             return (funcFlags & FunctionFlag.isscope) != 0;
4121         }
4122         /// ditto
4123         void isScopeQual(bool v) pure nothrow @safe @nogc
4124         {
4125             if (v) funcFlags |= FunctionFlag.isscope;
4126             else funcFlags &= ~FunctionFlag.isscope;
4127         }
4128 
4129         /// set or get if the function has the `return` attribute inferred
4130         bool isreturninferred() const pure nothrow @safe @nogc
4131         {
4132             return (funcFlags & FunctionFlag.isreturninferred) != 0;
4133         }
4134         /// ditto
4135         void isreturninferred(bool v) pure nothrow @safe @nogc
4136         {
4137             if (v) funcFlags |= FunctionFlag.isreturninferred;
4138             else funcFlags &= ~FunctionFlag.isreturninferred;
4139         }
4140 
4141         /// set or get if the function has the `scope` attribute inferred
4142         bool isscopeinferred() const pure nothrow @safe @nogc
4143         {
4144             return (funcFlags & FunctionFlag.isscopeinferred) != 0;
4145         }
4146         /// ditoo
4147         void isscopeinferred(bool v) pure nothrow @safe @nogc
4148         {
4149             if (v) funcFlags |= FunctionFlag.isscopeinferred;
4150             else funcFlags &= ~FunctionFlag.isscopeinferred;
4151         }
4152 
4153         /// set or get if the function has the `@live` attribute
4154         bool islive() const pure nothrow @safe @nogc
4155         {
4156             return (funcFlags & FunctionFlag.islive) != 0;
4157         }
4158         /// ditto
4159         void islive(bool v) pure nothrow @safe @nogc
4160         {
4161             if (v) funcFlags |= FunctionFlag.islive;
4162             else funcFlags &= ~FunctionFlag.islive;
4163         }
4164 
4165         /// set or get if the return type or the default arguments are removed
4166         bool incomplete() const pure nothrow @safe @nogc
4167         {
4168             return (funcFlags & FunctionFlag.incomplete) != 0;
4169         }
4170         /// ditto
4171         void incomplete(bool v) pure nothrow @safe @nogc
4172         {
4173             if (v) funcFlags |= FunctionFlag.incomplete;
4174             else funcFlags &= ~FunctionFlag.incomplete;
4175         }
4176 
4177         /// set or get if the function has the `inout` on the parameters
4178         bool isInOutParam() const pure nothrow @safe @nogc
4179         {
4180             return (funcFlags & FunctionFlag.inoutParam) != 0;
4181         }
4182         /// ditto
4183         void isInOutParam(bool v) pure nothrow @safe @nogc
4184         {
4185             if (v) funcFlags |= FunctionFlag.inoutParam;
4186             else funcFlags &= ~FunctionFlag.inoutParam;
4187         }
4188 
4189         /// set or get if the function has the `inout` on the parameters
4190         bool isInOutQual() const pure nothrow @safe @nogc
4191         {
4192             return (funcFlags & FunctionFlag.inoutQual) != 0;
4193         }
4194         /// ditto
4195         void isInOutQual(bool v) pure nothrow @safe @nogc
4196         {
4197             if (v) funcFlags |= FunctionFlag.inoutQual;
4198             else funcFlags &= ~FunctionFlag.inoutQual;
4199         }
4200         /// Returns: `true` the function is `isInOutQual` or `isInOutParam` ,`false` otherwise.
4201         bool iswild() const pure nothrow @safe @nogc
4202         {
4203             return (funcFlags & (FunctionFlag.inoutParam | FunctionFlag.inoutQual)) != 0;
4204         }
4205 
4206         override void accept(Visitor v)
4207         {
4208             v.visit(this);
4209         }
4210     }
4211 
4212     extern (C++) class TypeArray : TypeNext
4213     {
4214         final extern (D) this(TY ty, Type next)
4215         {
4216             super(ty, next);
4217         }
4218 
4219         override void accept(Visitor v)
4220         {
4221             v.visit(this);
4222         }
4223     }
4224 
4225     extern (C++) final class TypeDArray : TypeArray
4226     {
4227         extern (D) this(Type t)
4228         {
4229             super(Tarray, t);
4230         }
4231 
4232         override Type syntaxCopy()
4233         {
4234             Type t = next.syntaxCopy();
4235             if (t == next)
4236                 t = this;
4237             else
4238             {
4239                 t = new TypeDArray(t);
4240                 t.mod = mod;
4241             }
4242             return t;
4243         }
4244 
4245         override void accept(Visitor v)
4246         {
4247             v.visit(this);
4248         }
4249     }
4250 
4251     extern (C++) final class TypeAArray : TypeArray
4252     {
4253         Type index;
4254         Loc loc;
4255 
4256         extern (D) this(Type t, Type index)
4257         {
4258             super(Taarray, t);
4259             this.index = index;
4260         }
4261 
4262         override Type syntaxCopy()
4263         {
4264             Type t = next.syntaxCopy();
4265             Type ti = index.syntaxCopy();
4266             if (t == next && ti == index)
4267                 t = this;
4268             else
4269             {
4270                 t = new TypeAArray(t, ti);
4271                 t.mod = mod;
4272             }
4273             return t;
4274         }
4275 
4276         override Expression toExpression()
4277         {
4278             Expression e = next.toExpression();
4279             if (e)
4280             {
4281                 Expression ei = index.toExpression();
4282                 if (ei)
4283                     return new ArrayExp(loc, e, ei);
4284             }
4285             return null;
4286         }
4287 
4288         override void accept(Visitor v)
4289         {
4290             v.visit(this);
4291         }
4292     }
4293 
4294     extern (C++) final class TypeSArray : TypeArray
4295     {
4296         Expression dim;
4297 
4298         final extern (D) this(Type t, Expression dim)
4299         {
4300             super(Tsarray, t);
4301             this.dim = dim;
4302         }
4303 
4304         override Type syntaxCopy()
4305         {
4306             Type t = next.syntaxCopy();
4307             Expression e = dim.syntaxCopy();
4308             t = new TypeSArray(t, e);
4309             t.mod = mod;
4310             return t;
4311         }
4312 
4313         override Expression toExpression()
4314         {
4315             Expression e = next.toExpression();
4316             if (e)
4317                 e = new ArrayExp(dim.loc, e, dim);
4318             return e;
4319         }
4320 
4321         override void accept(Visitor v)
4322         {
4323             v.visit(this);
4324         }
4325     }
4326 
4327     extern (C++) abstract class TypeQualified : Type
4328     {
4329         Objects idents;
4330         Loc loc;
4331 
4332         final extern (D) this(TY ty, Loc loc)
4333         {
4334             super(ty);
4335             this.loc = loc;
4336         }
4337 
4338         final void addIdent(Identifier id)
4339         {
4340             idents.push(id);
4341         }
4342 
4343         final void addInst(TemplateInstance ti)
4344         {
4345             idents.push(ti);
4346         }
4347 
4348         final void addIndex(RootObject e)
4349         {
4350             idents.push(e);
4351         }
4352 
4353         final void syntaxCopyHelper(TypeQualified t)
4354         {
4355             idents.setDim(t.idents.dim);
4356             for (size_t i = 0; i < idents.dim; i++)
4357             {
4358                 RootObject id = t.idents[i];
4359                 if (id.dyncast() == DYNCAST.dsymbol)
4360                 {
4361                     TemplateInstance ti = cast(TemplateInstance)id;
4362                     ti = cast(TemplateInstance)ti.syntaxCopy(null);
4363                     id = ti;
4364                 }
4365                 else if (id.dyncast() == DYNCAST.expression)
4366                 {
4367                     Expression e = cast(Expression)id;
4368                     e = e.syntaxCopy();
4369                     id = e;
4370                 }
4371                 else if (id.dyncast() == DYNCAST.type)
4372                 {
4373                     Type tx = cast(Type)id;
4374                     tx = tx.syntaxCopy();
4375                     id = tx;
4376                 }
4377                 idents[i] = id;
4378             }
4379         }
4380 
4381         final Expression toExpressionHelper(Expression e, size_t i = 0)
4382         {
4383             for (; i < idents.dim; i++)
4384             {
4385                 RootObject id = idents[i];
4386 
4387                 switch (id.dyncast())
4388                 {
4389                     case DYNCAST.identifier:
4390                         e = new DotIdExp(e.loc, e, cast(Identifier)id);
4391                         break;
4392 
4393                     case DYNCAST.dsymbol:
4394                         auto ti = (cast(Dsymbol)id).isTemplateInstance();
4395                         assert(ti);
4396                         e = new DotTemplateInstanceExp(e.loc, e, ti.name, ti.tiargs);
4397                         break;
4398 
4399                     case DYNCAST.type:          // Bugzilla 1215
4400                         e = new ArrayExp(loc, e, new TypeExp(loc, cast(Type)id));
4401                         break;
4402 
4403                     case DYNCAST.expression:    // Bugzilla 1215
4404                         e = new ArrayExp(loc, e, cast(Expression)id);
4405                         break;
4406 
4407                     default:
4408                         assert(0);
4409                 }
4410             }
4411             return e;
4412         }
4413 
4414         override void accept(Visitor v)
4415         {
4416             v.visit(this);
4417         }
4418     }
4419 
4420     extern (C++) class TypeTraits : Type
4421     {
4422         TraitsExp exp;
4423         Loc loc;
4424 
4425         extern (D) this(const ref Loc loc, TraitsExp exp)
4426         {
4427             super(Tident);
4428             this.loc = loc;
4429             this.exp = exp;
4430         }
4431 
4432         override void accept(Visitor v)
4433         {
4434             v.visit(this);
4435         }
4436 
4437         override Type syntaxCopy()
4438         {
4439             TraitsExp te = cast(TraitsExp) exp.syntaxCopy();
4440             TypeTraits tt = new TypeTraits(loc, te);
4441             tt.mod = mod;
4442             return tt;
4443         }
4444     }
4445 
4446     extern (C++) final class TypeMixin : Type
4447     {
4448         Loc loc;
4449         Expressions* exps;
4450 
4451         extern (D) this(const ref Loc loc, Expressions* exps)
4452         {
4453             super(Tmixin);
4454             this.loc = loc;
4455             this.exps = exps;
4456         }
4457 
4458         override Type syntaxCopy()
4459         {
4460             static Expressions* arraySyntaxCopy(Expressions* exps)
4461             {
4462                 Expressions* a = null;
4463                 if (exps)
4464                 {
4465                     a = new Expressions(exps.dim);
4466                     foreach (i, e; *exps)
4467                     {
4468                         (*a)[i] = e ? e.syntaxCopy() : null;
4469                     }
4470                 }
4471                 return a;
4472             }
4473 
4474             return new TypeMixin(loc, arraySyntaxCopy(exps));
4475         }
4476 
4477         override void accept(Visitor v)
4478         {
4479             v.visit(this);
4480         }
4481     }
4482 
4483     extern (C++) final class TypeIdentifier : TypeQualified
4484     {
4485         Identifier ident;
4486 
4487         extern (D) this(const ref Loc loc, Identifier ident)
4488         {
4489             super(Tident, loc);
4490             this.ident = ident;
4491         }
4492 
4493         override Type syntaxCopy()
4494         {
4495             auto t = new TypeIdentifier(loc, ident);
4496             t.syntaxCopyHelper(this);
4497             t.mod = mod;
4498             return t;
4499         }
4500 
4501         override Expression toExpression()
4502         {
4503             return toExpressionHelper(new IdentifierExp(loc, ident));
4504         }
4505 
4506         override void accept(Visitor v)
4507         {
4508             v.visit(this);
4509         }
4510     }
4511 
4512     extern (C++) final class TypeReturn : TypeQualified
4513     {
4514         extern (D) this(const ref Loc loc)
4515         {
4516             super(Treturn, loc);
4517         }
4518 
4519         override Type syntaxCopy()
4520         {
4521             auto t = new TypeReturn(loc);
4522             t.syntaxCopyHelper(this);
4523             t.mod = mod;
4524             return t;
4525         }
4526 
4527         override void accept(Visitor v)
4528         {
4529             v.visit(this);
4530         }
4531     }
4532 
4533     extern (C++) final class TypeTypeof : TypeQualified
4534     {
4535         Expression exp;
4536 
4537         extern (D) this(const ref Loc loc, Expression exp)
4538         {
4539             super(Ttypeof, loc);
4540             this.exp = exp;
4541         }
4542 
4543         override Type syntaxCopy()
4544         {
4545             auto t = new TypeTypeof(loc, exp.syntaxCopy());
4546             t.syntaxCopyHelper(this);
4547             t.mod = mod;
4548             return t;
4549         }
4550 
4551         override void accept(Visitor v)
4552         {
4553             v.visit(this);
4554         }
4555     }
4556 
4557     extern (C++) final class TypeInstance : TypeQualified
4558     {
4559         TemplateInstance tempinst;
4560 
4561         final extern (D) this(const ref Loc loc, TemplateInstance tempinst)
4562         {
4563             super(Tinstance, loc);
4564             this.tempinst = tempinst;
4565         }
4566 
4567         override Type syntaxCopy()
4568         {
4569             auto t = new TypeInstance(loc, cast(TemplateInstance)tempinst.syntaxCopy(null));
4570             t.syntaxCopyHelper(this);
4571             t.mod = mod;
4572             return t;
4573         }
4574 
4575         override Expression toExpression()
4576         {
4577             return toExpressionHelper(new ScopeExp(loc, tempinst));
4578         }
4579 
4580         override void accept(Visitor v)
4581         {
4582             v.visit(this);
4583         }
4584     }
4585 
4586     extern (C++) abstract class Expression : ASTNode
4587     {
4588         TOK op;
4589         ubyte size;
4590         ubyte parens;
4591         Type type;
4592         Loc loc;
4593 
4594         final extern (D) this(const ref Loc loc, TOK op, int size)
4595         {
4596             this.loc = loc;
4597             this.op = op;
4598             this.size = cast(ubyte)size;
4599         }
4600 
4601         Expression syntaxCopy()
4602         {
4603             return copy();
4604         }
4605 
4606         final void error(const(char)* format, ...) const
4607         {
4608             if (type != Type.terror)
4609             {
4610                 va_list ap;
4611                 va_start(ap, format);
4612                 verror(loc, format, ap);
4613                 va_end(ap);
4614             }
4615         }
4616 
4617         final Expression copy()
4618         {
4619             Expression e;
4620             if (!size)
4621             {
4622                 assert(0);
4623             }
4624             e = cast(Expression)mem.xmalloc(size);
4625             return cast(Expression)memcpy(cast(void*)e, cast(void*)this, size);
4626         }
4627 
4628         override final DYNCAST dyncast() const
4629         {
4630             return DYNCAST.expression;
4631         }
4632 
4633         override void accept(Visitor v)
4634         {
4635             v.visit(this);
4636         }
4637     }
4638 
4639     extern (C++) final class DeclarationExp : Expression
4640     {
4641         Dsymbol declaration;
4642 
4643         extern (D) this(const ref Loc loc, Dsymbol declaration)
4644         {
4645             super(loc, TOK.declaration, __traits(classInstanceSize, DeclarationExp));
4646             this.declaration = declaration;
4647         }
4648 
4649         override void accept(Visitor v)
4650         {
4651             v.visit(this);
4652         }
4653     }
4654 
4655     extern (C++) final class IntegerExp : Expression
4656     {
4657         dinteger_t value;
4658 
4659         extern (D) this(const ref Loc loc, dinteger_t value, Type type)
4660         {
4661             super(loc, TOK.int64, __traits(classInstanceSize, IntegerExp));
4662             assert(type);
4663             if (!type.isscalar())
4664             {
4665                 if (type.ty != Terror)
4666                     error("integral constant must be scalar type, not %s", type.toChars());
4667                 type = Type.terror;
4668             }
4669             this.type = type;
4670             setInteger(value);
4671         }
4672 
4673         void setInteger(dinteger_t value)
4674         {
4675             this.value = value;
4676             normalize();
4677         }
4678 
4679         void normalize()
4680         {
4681             /* 'Normalize' the value of the integer to be in range of the type
4682              */
4683             switch (type.toBasetype().ty)
4684             {
4685             case Tbool:
4686                 value = (value != 0);
4687                 break;
4688 
4689             case Tint8:
4690                 value = cast(d_int8)value;
4691                 break;
4692 
4693             case Tchar:
4694             case Tuns8:
4695                 value = cast(d_uns8)value;
4696                 break;
4697 
4698             case Tint16:
4699                 value = cast(d_int16)value;
4700                 break;
4701 
4702             case Twchar:
4703             case Tuns16:
4704                 value = cast(d_uns16)value;
4705                 break;
4706 
4707             case Tint32:
4708                 value = cast(d_int32)value;
4709                 break;
4710 
4711             case Tdchar:
4712             case Tuns32:
4713                 value = cast(d_uns32)value;
4714                 break;
4715 
4716             case Tint64:
4717                 value = cast(d_int64)value;
4718                 break;
4719 
4720             case Tuns64:
4721                 value = cast(d_uns64)value;
4722                 break;
4723 
4724             case Tpointer:
4725                 if (Target.ptrsize == 8)
4726                     goto case Tuns64;
4727                 if (Target.ptrsize == 4)
4728                     goto case Tuns32;
4729                 if (Target.ptrsize == 2)
4730                     goto case Tuns16;
4731                 assert(0);
4732 
4733             default:
4734                 break;
4735             }
4736         }
4737 
4738         override void accept(Visitor v)
4739         {
4740             v.visit(this);
4741         }
4742     }
4743 
4744     extern (C++) final class NewAnonClassExp : Expression
4745     {
4746         Expression thisexp;     // if !=null, 'this' for class being allocated
4747         Expressions* newargs;   // Array of Expression's to call new operator
4748         ClassDeclaration cd;    // class being instantiated
4749         Expressions* arguments; // Array of Expression's to call class constructor
4750 
4751         extern (D) this(const ref Loc loc, Expression thisexp, Expressions* newargs, ClassDeclaration cd, Expressions* arguments)
4752         {
4753             super(loc, TOK.newAnonymousClass, __traits(classInstanceSize, NewAnonClassExp));
4754             this.thisexp = thisexp;
4755             this.newargs = newargs;
4756             this.cd = cd;
4757             this.arguments = arguments;
4758         }
4759 
4760         override void accept(Visitor v)
4761         {
4762             v.visit(this);
4763         }
4764     }
4765 
4766     extern (C++) final class IsExp : Expression
4767     {
4768         Type targ;
4769         Identifier id;      // can be null
4770         Type tspec;         // can be null
4771         TemplateParameters* parameters;
4772         TOK tok;            // ':' or '=='
4773         TOK tok2;           // 'struct', 'union', etc.
4774 
4775         extern (D) this(const ref Loc loc, Type targ, Identifier id, TOK tok, Type tspec, TOK tok2, TemplateParameters* parameters)
4776         {
4777             super(loc, TOK.is_, __traits(classInstanceSize, IsExp));
4778             this.targ = targ;
4779             this.id = id;
4780             this.tok = tok;
4781             this.tspec = tspec;
4782             this.tok2 = tok2;
4783             this.parameters = parameters;
4784         }
4785 
4786         override void accept(Visitor v)
4787         {
4788             v.visit(this);
4789         }
4790     }
4791 
4792     extern (C++) final class RealExp : Expression
4793     {
4794         real_t value;
4795 
4796         extern (D) this(const ref Loc loc, real_t value, Type type)
4797         {
4798             super(loc, TOK.float64, __traits(classInstanceSize, RealExp));
4799             this.value = value;
4800             this.type = type;
4801         }
4802 
4803         override void accept(Visitor v)
4804         {
4805             v.visit(this);
4806         }
4807     }
4808 
4809     extern (C++) final class NullExp : Expression
4810     {
4811         extern (D) this(const ref Loc loc, Type type = null)
4812         {
4813             super(loc, TOK.null_, __traits(classInstanceSize, NullExp));
4814             this.type = type;
4815         }
4816 
4817         override void accept(Visitor v)
4818         {
4819             v.visit(this);
4820         }
4821     }
4822 
4823     extern (C++) final class TypeidExp : Expression
4824     {
4825         RootObject obj;
4826 
4827         extern (D) this(const ref Loc loc, RootObject o)
4828         {
4829             super(loc, TOK.typeid_, __traits(classInstanceSize, TypeidExp));
4830             this.obj = o;
4831         }
4832 
4833         override void accept(Visitor v)
4834         {
4835             v.visit(this);
4836         }
4837     }
4838 
4839     extern (C++) final class TraitsExp : Expression
4840     {
4841         Identifier ident;
4842         Objects* args;
4843 
4844         extern (D) this(const ref Loc loc, Identifier ident, Objects* args)
4845         {
4846             super(loc, TOK.traits, __traits(classInstanceSize, TraitsExp));
4847             this.ident = ident;
4848             this.args = args;
4849         }
4850 
4851         override void accept(Visitor v)
4852         {
4853             v.visit(this);
4854         }
4855     }
4856 
4857     extern (C++) final class StringExp : Expression
4858     {
4859         union
4860         {
4861             char* string;   // if sz == 1
4862             wchar* wstring; // if sz == 2
4863             dchar* dstring; // if sz == 4
4864         }                   // (const if ownedByCtfe == OwnedBy.code)
4865         size_t len;         // number of code units
4866         ubyte sz = 1;       // 1: char, 2: wchar, 4: dchar
4867         char postfix = 0;   // 'c', 'w', 'd'
4868 
4869         extern (D) this(const ref Loc loc, const(void)[] string)
4870         {
4871             super(loc, TOK.string_, __traits(classInstanceSize, StringExp));
4872             this.string = cast(char*)string.ptr;
4873             this.len = string.length;
4874             this.sz = 1;                    // work around LDC bug #1286
4875         }
4876 
4877         extern (D) this(const ref Loc loc, const(void)[] string, size_t len, ubyte sz, char postfix = 0)
4878         {
4879             super(loc, TOK.string_, __traits(classInstanceSize, StringExp));
4880             this.string = cast(char*)string;
4881             this.len = len;
4882             this.postfix = postfix;
4883             this.sz = 1;                    // work around LDC bug #1286
4884         }
4885 
4886         /**********************************************
4887         * Write the contents of the string to dest.
4888         * Use numberOfCodeUnits() to determine size of result.
4889         * Params:
4890         *  dest = destination
4891         *  tyto = encoding type of the result
4892         *  zero = add terminating 0
4893         */
4894         void writeTo(void* dest, bool zero, int tyto = 0) const
4895         {
4896             int encSize;
4897             switch (tyto)
4898             {
4899                 case 0:      encSize = sz; break;
4900                 case Tchar:  encSize = 1; break;
4901                 case Twchar: encSize = 2; break;
4902                 case Tdchar: encSize = 4; break;
4903                 default:
4904                     assert(0);
4905             }
4906             if (sz == encSize)
4907             {
4908                 memcpy(dest, string, len * sz);
4909                 if (zero)
4910                     memset(dest + len * sz, 0, sz);
4911             }
4912             else
4913                 assert(0);
4914         }
4915 
4916         extern (D) const(char)[] toStringz() const
4917         {
4918             auto nbytes = len * sz;
4919             char* s = cast(char*)mem.xmalloc_noscan(nbytes + sz);
4920             writeTo(s, true);
4921             return s[0 .. nbytes];
4922         }
4923 
4924         override void accept(Visitor v)
4925         {
4926             v.visit(this);
4927         }
4928     }
4929 
4930     extern (C++) class NewExp : Expression
4931     {
4932         Expression thisexp;         // if !=null, 'this' for class being allocated
4933         Expressions* newargs;       // Array of Expression's to call new operator
4934         Type newtype;
4935         Expressions* arguments;     // Array of Expression's
4936 
4937         extern (D) this(const ref Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
4938         {
4939             super(loc, TOK.new_, __traits(classInstanceSize, NewExp));
4940             this.thisexp = thisexp;
4941             this.newargs = newargs;
4942             this.newtype = newtype;
4943             this.arguments = arguments;
4944         }
4945 
4946         override void accept(Visitor v)
4947         {
4948             v.visit(this);
4949         }
4950     }
4951 
4952     extern (C++) final class AssocArrayLiteralExp : Expression
4953     {
4954         Expressions* keys;
4955         Expressions* values;
4956 
4957         extern (D) this(const ref Loc loc, Expressions* keys, Expressions* values)
4958         {
4959             super(loc, TOK.assocArrayLiteral, __traits(classInstanceSize, AssocArrayLiteralExp));
4960             assert(keys.dim == values.dim);
4961             this.keys = keys;
4962             this.values = values;
4963         }
4964 
4965         override void accept(Visitor v)
4966         {
4967             v.visit(this);
4968         }
4969     }
4970 
4971     extern (C++) final class ArrayLiteralExp : Expression
4972     {
4973         Expression basis;
4974         Expressions* elements;
4975 
4976         extern (D) this(const ref Loc loc, Expressions* elements)
4977         {
4978             super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
4979             this.elements = elements;
4980         }
4981 
4982         extern (D) this(const ref Loc loc, Expression e)
4983         {
4984             super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
4985             elements = new Expressions();
4986             elements.push(e);
4987         }
4988 
4989         extern (D) this(const ref Loc loc, Expression basis, Expressions* elements)
4990         {
4991             super(loc, TOK.arrayLiteral, __traits(classInstanceSize, ArrayLiteralExp));
4992             this.basis = basis;
4993             this.elements = elements;
4994         }
4995 
4996         override void accept(Visitor v)
4997         {
4998             v.visit(this);
4999         }
5000     }
5001 
5002     extern (C++) final class FuncExp : Expression
5003     {
5004         FuncLiteralDeclaration fd;
5005         TemplateDeclaration td;
5006         TOK tok;
5007 
5008         extern (D) this(const ref Loc loc, Dsymbol s)
5009         {
5010             super(loc, TOK.function_, __traits(classInstanceSize, FuncExp));
5011             this.td = s.isTemplateDeclaration();
5012             this.fd = s.isFuncLiteralDeclaration();
5013             if (td)
5014             {
5015                 assert(td.literal);
5016                 assert(td.members && td.members.dim == 1);
5017                 fd = (*td.members)[0].isFuncLiteralDeclaration();
5018             }
5019             tok = fd.tok; // save original kind of function/delegate/(infer)
5020             assert(fd.fbody);
5021         }
5022 
5023         override void accept(Visitor v)
5024         {
5025             v.visit(this);
5026         }
5027     }
5028 
5029     extern (C++) final class IntervalExp : Expression
5030     {
5031         Expression lwr;
5032         Expression upr;
5033 
5034         extern (D) this(const ref Loc loc, Expression lwr, Expression upr)
5035         {
5036             super(loc, TOK.interval, __traits(classInstanceSize, IntervalExp));
5037             this.lwr = lwr;
5038             this.upr = upr;
5039         }
5040 
5041         override void accept(Visitor v)
5042         {
5043             v.visit(this);
5044         }
5045     }
5046 
5047     extern (C++) final class TypeExp : Expression
5048     {
5049         extern (D) this(const ref Loc loc, Type type)
5050         {
5051             super(loc, TOK.type, __traits(classInstanceSize, TypeExp));
5052             this.type = type;
5053         }
5054 
5055         override void accept(Visitor v)
5056         {
5057             v.visit(this);
5058         }
5059     }
5060 
5061     extern (C++) final class ScopeExp : Expression
5062     {
5063         ScopeDsymbol sds;
5064 
5065         extern (D) this(const ref Loc loc, ScopeDsymbol sds)
5066         {
5067             super(loc, TOK.scope_, __traits(classInstanceSize, ScopeExp));
5068             this.sds = sds;
5069             assert(!sds.isTemplateDeclaration());
5070         }
5071 
5072         override void accept(Visitor v)
5073         {
5074             v.visit(this);
5075         }
5076     }
5077 
5078     extern (C++) class IdentifierExp : Expression
5079     {
5080         Identifier ident;
5081 
5082         final extern (D) this(const ref Loc loc, Identifier ident)
5083         {
5084             super(loc, TOK.identifier, __traits(classInstanceSize, IdentifierExp));
5085             this.ident = ident;
5086         }
5087 
5088         override void accept(Visitor v)
5089         {
5090             v.visit(this);
5091         }
5092     }
5093 
5094     extern (C++) class UnaExp : Expression
5095     {
5096         Expression e1;
5097 
5098         final extern (D) this(const ref Loc loc, TOK op, int size, Expression e1)
5099         {
5100             super(loc, op, size);
5101             this.e1 = e1;
5102         }
5103 
5104         override void accept(Visitor v)
5105         {
5106             v.visit(this);
5107         }
5108     }
5109 
5110     extern (C++) class DefaultInitExp : Expression
5111     {
5112         final extern (D) this(const ref Loc loc, TOK op, int size)
5113         {
5114             super(loc, op, size);
5115         }
5116 
5117         override void accept(Visitor v)
5118         {
5119             v.visit(this);
5120         }
5121     }
5122 
5123     extern (C++) abstract class BinExp : Expression
5124     {
5125         Expression e1;
5126         Expression e2;
5127 
5128         final extern (D) this(const ref Loc loc, TOK op, int size, Expression e1, Expression e2)
5129         {
5130             super(loc, op, size);
5131             this.e1 = e1;
5132             this.e2 = e2;
5133         }
5134 
5135         override void accept(Visitor v)
5136         {
5137             v.visit(this);
5138         }
5139     }
5140 
5141     extern (C++) final class DsymbolExp : Expression
5142     {
5143         Dsymbol s;
5144         bool hasOverloads;
5145 
5146         extern (D) this(const ref Loc loc, Dsymbol s, bool hasOverloads = true)
5147         {
5148             super(loc, TOK.dSymbol, __traits(classInstanceSize, DsymbolExp));
5149             this.s = s;
5150             this.hasOverloads = hasOverloads;
5151         }
5152 
5153         override void accept(Visitor v)
5154         {
5155             v.visit(this);
5156         }
5157     }
5158 
5159     extern (C++) final class TemplateExp : Expression
5160     {
5161         TemplateDeclaration td;
5162         FuncDeclaration fd;
5163 
5164         extern (D) this(const ref Loc loc, TemplateDeclaration td, FuncDeclaration fd = null)
5165         {
5166             super(loc, TOK.template_, __traits(classInstanceSize, TemplateExp));
5167             //printf("TemplateExp(): %s\n", td.toChars());
5168             this.td = td;
5169             this.fd = fd;
5170         }
5171 
5172         override void accept(Visitor v)
5173         {
5174             v.visit(this);
5175         }
5176     }
5177 
5178     extern (C++) class SymbolExp : Expression
5179     {
5180         Declaration var;
5181         bool hasOverloads;
5182 
5183         final extern (D) this(const ref Loc loc, TOK op, int size, Declaration var, bool hasOverloads)
5184         {
5185             super(loc, op, size);
5186             assert(var);
5187             this.var = var;
5188             this.hasOverloads = hasOverloads;
5189         }
5190 
5191         override void accept(Visitor v)
5192         {
5193             v.visit(this);
5194         }
5195     }
5196 
5197     extern (C++) final class VarExp : SymbolExp
5198     {
5199         extern (D) this(const ref Loc loc, Declaration var, bool hasOverloads = true)
5200         {
5201             if (var.isVarDeclaration())
5202                 hasOverloads = false;
5203 
5204             super(loc, TOK.variable, __traits(classInstanceSize, VarExp), var, hasOverloads);
5205             this.type = var.type;
5206         }
5207 
5208         override void accept(Visitor v)
5209         {
5210             v.visit(this);
5211         }
5212     }
5213 
5214     extern (C++) final class TupleExp : Expression
5215     {
5216         Expression e0;
5217         Expressions* exps;
5218 
5219         extern (D) this(const ref Loc loc, Expression e0, Expressions* exps)
5220         {
5221             super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
5222             //printf("TupleExp(this = %p)\n", this);
5223             this.e0 = e0;
5224             this.exps = exps;
5225         }
5226 
5227         extern (D) this(const ref Loc loc, Expressions* exps)
5228         {
5229             super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
5230             //printf("TupleExp(this = %p)\n", this);
5231             this.exps = exps;
5232         }
5233 
5234         extern (D) this(const ref Loc loc, TupleDeclaration tup)
5235         {
5236             super(loc, TOK.tuple, __traits(classInstanceSize, TupleExp));
5237             this.exps = new Expressions();
5238 
5239             this.exps.reserve(tup.objects.dim);
5240             for (size_t i = 0; i < tup.objects.dim; i++)
5241             {
5242                 RootObject o = (*tup.objects)[i];
5243                 if (Dsymbol s = getDsymbol(o))
5244                 {
5245                     Expression e = new DsymbolExp(loc, s);
5246                     this.exps.push(e);
5247                 }
5248                 else if (o.dyncast() == DYNCAST.expression)
5249                 {
5250                     auto e = (cast(Expression)o).copy();
5251                     e.loc = loc;    // Bugzilla 15669
5252                     this.exps.push(e);
5253                 }
5254                 else if (o.dyncast() == DYNCAST.type)
5255                 {
5256                     Type t = cast(Type)o;
5257                     Expression e = new TypeExp(loc, t);
5258                     this.exps.push(e);
5259                 }
5260                 else
5261                 {
5262                     error("%s is not an expression", o.toChars());
5263                 }
5264             }
5265         }
5266 
5267         extern (C++) Dsymbol isDsymbol(RootObject o)
5268         {
5269             if (!o || o.dyncast || DYNCAST.dsymbol)
5270                 return null;
5271             return cast(Dsymbol)o;
5272         }
5273 
5274         extern (C++) Dsymbol getDsymbol(RootObject oarg)
5275         {
5276             Dsymbol sa;
5277             Expression ea = isExpression(oarg);
5278             if (ea)
5279             {
5280                 // Try to convert Expression to symbol
5281                 if (ea.op == TOK.variable)
5282                     sa = (cast(VarExp)ea).var;
5283                 else if (ea.op == TOK.function_)
5284                 {
5285                     if ((cast(FuncExp)ea).td)
5286                         sa = (cast(FuncExp)ea).td;
5287                     else
5288                         sa = (cast(FuncExp)ea).fd;
5289                 }
5290                 else if (ea.op == TOK.template_)
5291                     sa = (cast(TemplateExp)ea).td;
5292                 else
5293                     sa = null;
5294             }
5295             else
5296             {
5297                 // Try to convert Type to symbol
5298                 Type ta = isType(oarg);
5299                 if (ta)
5300                     sa = ta.toDsymbol(null);
5301                 else
5302                     sa = isDsymbol(oarg); // if already a symbol
5303             }
5304             return sa;
5305         }
5306 
5307         override void accept(Visitor v)
5308         {
5309             v.visit(this);
5310         }
5311     }
5312 
5313     extern (C++) final class DollarExp : IdentifierExp
5314     {
5315         extern (D) this(const ref Loc loc)
5316         {
5317             super(loc, Id.dollar);
5318         }
5319 
5320         override void accept(Visitor v)
5321         {
5322             v.visit(this);
5323         }
5324     }
5325 
5326     extern (C++) class ThisExp : Expression
5327     {
5328         final extern (D) this(const ref Loc loc)
5329         {
5330             super(loc, TOK.this_, __traits(classInstanceSize, ThisExp));
5331         }
5332 
5333         override void accept(Visitor v)
5334         {
5335             v.visit(this);
5336         }
5337     }
5338 
5339     extern (C++) final class SuperExp : ThisExp
5340     {
5341         extern (D) this(const ref Loc loc)
5342         {
5343             super(loc);
5344             op = TOK.super_;
5345         }
5346 
5347         override void accept(Visitor v)
5348         {
5349             v.visit(this);
5350         }
5351     }
5352 
5353     extern (C++) final class AddrExp : UnaExp
5354     {
5355         extern (D) this(const ref Loc loc, Expression e)
5356         {
5357             super(loc, TOK.address, __traits(classInstanceSize, AddrExp), e);
5358         }
5359 
5360         override void accept(Visitor v)
5361         {
5362             v.visit(this);
5363         }
5364     }
5365 
5366     extern (C++) final class PreExp : UnaExp
5367     {
5368         extern (D) this(TOK op, Loc loc, Expression e)
5369         {
5370             super(loc, op, __traits(classInstanceSize, PreExp), e);
5371         }
5372 
5373         override void accept(Visitor v)
5374         {
5375             v.visit(this);
5376         }
5377     }
5378 
5379     extern (C++) final class PtrExp : UnaExp
5380     {
5381         extern (D) this(const ref Loc loc, Expression e)
5382         {
5383             super(loc, TOK.star, __traits(classInstanceSize, PtrExp), e);
5384         }
5385         extern (D) this(const ref Loc loc, Expression e, Type t)
5386         {
5387             super(loc, TOK.star, __traits(classInstanceSize, PtrExp), e);
5388             type = t;
5389         }
5390 
5391         override void accept(Visitor v)
5392         {
5393             v.visit(this);
5394         }
5395     }
5396 
5397     extern (C++) final class NegExp : UnaExp
5398     {
5399         extern (D) this(const ref Loc loc, Expression e)
5400         {
5401             super(loc, TOK.negate, __traits(classInstanceSize, NegExp), e);
5402         }
5403 
5404         override void accept(Visitor v)
5405         {
5406             v.visit(this);
5407         }
5408     }
5409 
5410     extern (C++) final class UAddExp : UnaExp
5411     {
5412         extern (D) this(const ref Loc loc, Expression e)
5413         {
5414             super(loc, TOK.uadd, __traits(classInstanceSize, UAddExp), e);
5415         }
5416 
5417         override void accept(Visitor v)
5418         {
5419             v.visit(this);
5420         }
5421     }
5422 
5423     extern (C++) final class NotExp : UnaExp
5424     {
5425         extern (D) this(const ref Loc loc, Expression e)
5426         {
5427             super(loc, TOK.not, __traits(classInstanceSize, NotExp), e);
5428         }
5429 
5430         override void accept(Visitor v)
5431         {
5432             v.visit(this);
5433         }
5434     }
5435 
5436     extern (C++) final class ComExp : UnaExp
5437     {
5438         extern (D) this(const ref Loc loc, Expression e)
5439         {
5440             super(loc, TOK.tilde, __traits(classInstanceSize, ComExp), e);
5441         }
5442 
5443         override void accept(Visitor v)
5444         {
5445             v.visit(this);
5446         }
5447     }
5448 
5449     extern (C++) final class DeleteExp : UnaExp
5450     {
5451         bool isRAII;
5452 
5453         extern (D) this(const ref Loc loc, Expression e, bool isRAII)
5454         {
5455             super(loc, TOK.delete_, __traits(classInstanceSize, DeleteExp), e);
5456             this.isRAII = isRAII;
5457         }
5458 
5459         override void accept(Visitor v)
5460         {
5461             v.visit(this);
5462         }
5463     }
5464 
5465     extern (C++) final class CastExp : UnaExp
5466     {
5467         Type to;
5468         ubyte mod = cast(ubyte)~0;
5469 
5470         extern (D) this(const ref Loc loc, Expression e, Type t)
5471         {
5472             super(loc, TOK.cast_, __traits(classInstanceSize, CastExp), e);
5473             this.to = t;
5474         }
5475         extern (D) this(const ref Loc loc, Expression e, ubyte mod)
5476         {
5477             super(loc, TOK.cast_, __traits(classInstanceSize, CastExp), e);
5478             this.mod = mod;
5479         }
5480 
5481         override void accept(Visitor v)
5482         {
5483             v.visit(this);
5484         }
5485     }
5486 
5487     extern (C++) final class CallExp : UnaExp
5488     {
5489         Expressions* arguments;
5490 
5491         extern (D) this(const ref Loc loc, Expression e, Expressions* exps)
5492         {
5493             super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
5494             this.arguments = exps;
5495         }
5496 
5497         extern (D) this(const ref Loc loc, Expression e)
5498         {
5499             super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
5500         }
5501 
5502         extern (D) this(const ref Loc loc, Expression e, Expression earg1)
5503         {
5504             super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
5505             auto arguments = new Expressions();
5506             if (earg1)
5507             {
5508                 arguments.setDim(1);
5509                 (*arguments)[0] = earg1;
5510             }
5511             this.arguments = arguments;
5512         }
5513 
5514         extern (D) this(const ref Loc loc, Expression e, Expression earg1, Expression earg2)
5515         {
5516             super(loc, TOK.call, __traits(classInstanceSize, CallExp), e);
5517             auto arguments = new Expressions();
5518             arguments.setDim(2);
5519             (*arguments)[0] = earg1;
5520             (*arguments)[1] = earg2;
5521             this.arguments = arguments;
5522         }
5523 
5524         override void accept(Visitor v)
5525         {
5526             v.visit(this);
5527         }
5528     }
5529 
5530     extern (C++) final class DotIdExp : UnaExp
5531     {
5532         Identifier ident;
5533 
5534         extern (D) this(const ref Loc loc, Expression e, Identifier ident)
5535         {
5536             super(loc, TOK.dotIdentifier, __traits(classInstanceSize, DotIdExp), e);
5537             this.ident = ident;
5538         }
5539 
5540         override void accept(Visitor v)
5541         {
5542             v.visit(this);
5543         }
5544     }
5545 
5546     extern (C++) final class AssertExp : UnaExp
5547     {
5548         Expression msg;
5549 
5550         extern (D) this(const ref Loc loc, Expression e, Expression msg = null)
5551         {
5552             super(loc, TOK.assert_, __traits(classInstanceSize, AssertExp), e);
5553             this.msg = msg;
5554         }
5555 
5556         override void accept(Visitor v)
5557         {
5558             v.visit(this);
5559         }
5560     }
5561 
5562     extern (C++) final class CompileExp : Expression
5563     {
5564         Expressions* exps;
5565 
5566         extern (D) this(const ref Loc loc, Expressions* exps)
5567         {
5568             super(loc, TOK.mixin_, __traits(classInstanceSize, CompileExp));
5569             this.exps = exps;
5570         }
5571 
5572         override void accept(Visitor v)
5573         {
5574             v.visit(this);
5575         }
5576     }
5577 
5578     extern (C++) final class ImportExp : UnaExp
5579     {
5580         extern (D) this(const ref Loc loc, Expression e)
5581         {
5582             super(loc, TOK.import_, __traits(classInstanceSize, ImportExp), e);
5583         }
5584 
5585         override void accept(Visitor v)
5586         {
5587             v.visit(this);
5588         }
5589     }
5590 
5591     extern (C++) final class DotTemplateInstanceExp : UnaExp
5592     {
5593         TemplateInstance ti;
5594 
5595         extern (D) this(const ref Loc loc, Expression e, Identifier name, Objects* tiargs)
5596         {
5597             super(loc, TOK.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
5598             this.ti = new TemplateInstance(loc, name, tiargs);
5599         }
5600         extern (D) this(const ref Loc loc, Expression e, TemplateInstance ti)
5601         {
5602             super(loc, TOK.dotTemplateInstance, __traits(classInstanceSize, DotTemplateInstanceExp), e);
5603             this.ti = ti;
5604         }
5605 
5606         override void accept(Visitor v)
5607         {
5608             v.visit(this);
5609         }
5610     }
5611 
5612     extern (C++) final class ArrayExp : UnaExp
5613     {
5614         Expressions* arguments;
5615 
5616         extern (D) this(const ref Loc loc, Expression e1, Expression index = null)
5617         {
5618             super(loc, TOK.array, __traits(classInstanceSize, ArrayExp), e1);
5619             arguments = new Expressions();
5620             if (index)
5621                 arguments.push(index);
5622         }
5623 
5624         extern (D) this(const ref Loc loc, Expression e1, Expressions* args)
5625         {
5626             super(loc, TOK.array, __traits(classInstanceSize, ArrayExp), e1);
5627             arguments = args;
5628         }
5629 
5630         override void accept(Visitor v)
5631         {
5632             v.visit(this);
5633         }
5634     }
5635 
5636     extern (C++) final class FuncInitExp : DefaultInitExp
5637     {
5638         extern (D) this(const ref Loc loc)
5639         {
5640             super(loc, TOK.functionString, __traits(classInstanceSize, FuncInitExp));
5641         }
5642 
5643         override void accept(Visitor v)
5644         {
5645             v.visit(this);
5646         }
5647     }
5648 
5649     extern (C++) final class PrettyFuncInitExp : DefaultInitExp
5650     {
5651         extern (D) this(const ref Loc loc)
5652         {
5653             super(loc, TOK.prettyFunction, __traits(classInstanceSize, PrettyFuncInitExp));
5654         }
5655 
5656         override void accept(Visitor v)
5657         {
5658             v.visit(this);
5659         }
5660     }
5661 
5662     extern (C++) final class FileInitExp : DefaultInitExp
5663     {
5664         extern (D) this(const ref Loc loc, TOK tok)
5665         {
5666             super(loc, tok, __traits(classInstanceSize, FileInitExp));
5667         }
5668 
5669         override void accept(Visitor v)
5670         {
5671             v.visit(this);
5672         }
5673     }
5674 
5675     extern (C++) final class LineInitExp : DefaultInitExp
5676     {
5677         extern (D) this(const ref Loc loc)
5678         {
5679             super(loc, TOK.line, __traits(classInstanceSize, LineInitExp));
5680         }
5681 
5682         override void accept(Visitor v)
5683         {
5684             v.visit(this);
5685         }
5686     }
5687 
5688     extern (C++) final class ModuleInitExp : DefaultInitExp
5689     {
5690         extern (D) this(const ref Loc loc)
5691         {
5692             super(loc, TOK.moduleString, __traits(classInstanceSize, ModuleInitExp));
5693         }
5694 
5695         override void accept(Visitor v)
5696         {
5697             v.visit(this);
5698         }
5699     }
5700 
5701     extern (C++) final class CommaExp : BinExp
5702     {
5703         const bool isGenerated;
5704         bool allowCommaExp;
5705 
5706         extern (D) this(const ref Loc loc, Expression e1, Expression e2, bool generated = true)
5707         {
5708             super(loc, TOK.comma, __traits(classInstanceSize, CommaExp), e1, e2);
5709             allowCommaExp = isGenerated = generated;
5710         }
5711 
5712         override void accept(Visitor v)
5713         {
5714             v.visit(this);
5715         }
5716     }
5717 
5718     extern (C++) final class PostExp : BinExp
5719     {
5720         extern (D) this(TOK op, Loc loc, Expression e)
5721         {
5722             super(loc, op, __traits(classInstanceSize, PostExp), e, new IntegerExp(loc, 1, Type.tint32));
5723         }
5724 
5725         override void accept(Visitor v)
5726         {
5727             v.visit(this);
5728         }
5729     }
5730 
5731     extern (C++) final class PowExp : BinExp
5732     {
5733         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5734         {
5735             super(loc, TOK.pow, __traits(classInstanceSize, PowExp), e1, e2);
5736         }
5737 
5738         override void accept(Visitor v)
5739         {
5740             v.visit(this);
5741         }
5742     }
5743 
5744     extern (C++) final class MulExp : BinExp
5745     {
5746         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5747         {
5748             super(loc, TOK.mul, __traits(classInstanceSize, MulExp), e1, e2);
5749         }
5750 
5751         override void accept(Visitor v)
5752         {
5753             v.visit(this);
5754         }
5755     }
5756 
5757     extern (C++) final class DivExp : BinExp
5758     {
5759         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5760         {
5761             super(loc, TOK.div, __traits(classInstanceSize, DivExp), e1, e2);
5762         }
5763 
5764         override void accept(Visitor v)
5765         {
5766             v.visit(this);
5767         }
5768     }
5769 
5770     extern (C++) final class ModExp : BinExp
5771     {
5772         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5773         {
5774             super(loc, TOK.mod, __traits(classInstanceSize, ModExp), e1, e2);
5775         }
5776 
5777         override void accept(Visitor v)
5778         {
5779             v.visit(this);
5780         }
5781     }
5782 
5783     extern (C++) final class AddExp : BinExp
5784     {
5785         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5786         {
5787             super(loc, TOK.add, __traits(classInstanceSize, AddExp), e1, e2);
5788         }
5789 
5790         override void accept(Visitor v)
5791         {
5792             v.visit(this);
5793         }
5794     }
5795 
5796     extern (C++) final class MinExp : BinExp
5797     {
5798         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5799         {
5800             super(loc, TOK.min, __traits(classInstanceSize, MinExp), e1, e2);
5801         }
5802 
5803         override void accept(Visitor v)
5804         {
5805             v.visit(this);
5806         }
5807     }
5808 
5809     extern (C++) final class CatExp : BinExp
5810     {
5811         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5812         {
5813             super(loc, TOK.concatenate, __traits(classInstanceSize, CatExp), e1, e2);
5814         }
5815 
5816         override void accept(Visitor v)
5817         {
5818             v.visit(this);
5819         }
5820     }
5821 
5822     extern (C++) final class ShlExp : BinExp
5823     {
5824         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5825         {
5826             super(loc, TOK.leftShift, __traits(classInstanceSize, ShlExp), e1, e2);
5827         }
5828 
5829         override void accept(Visitor v)
5830         {
5831             v.visit(this);
5832         }
5833     }
5834 
5835     extern (C++) final class ShrExp : BinExp
5836     {
5837         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5838         {
5839             super(loc, TOK.rightShift, __traits(classInstanceSize, ShrExp), e1, e2);
5840         }
5841 
5842         override void accept(Visitor v)
5843         {
5844             v.visit(this);
5845         }
5846     }
5847 
5848     extern (C++) final class UshrExp : BinExp
5849     {
5850         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5851         {
5852             super(loc, TOK.unsignedRightShift, __traits(classInstanceSize, UshrExp), e1, e2);
5853         }
5854 
5855         override void accept(Visitor v)
5856         {
5857             v.visit(this);
5858         }
5859     }
5860 
5861     extern (C++) final class EqualExp : BinExp
5862     {
5863         extern (D) this(TOK op, Loc loc, Expression e1, Expression e2)
5864         {
5865             super(loc, op, __traits(classInstanceSize, EqualExp), e1, e2);
5866             assert(op == TOK.equal || op == TOK.notEqual);
5867         }
5868 
5869         override void accept(Visitor v)
5870         {
5871             v.visit(this);
5872         }
5873     }
5874 
5875     extern (C++) final class InExp : BinExp
5876     {
5877         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5878         {
5879             super(loc, TOK.in_, __traits(classInstanceSize, InExp), e1, e2);
5880         }
5881 
5882         override void accept(Visitor v)
5883         {
5884             v.visit(this);
5885         }
5886     }
5887 
5888     extern (C++) final class IdentityExp : BinExp
5889     {
5890         extern (D) this(TOK op, Loc loc, Expression e1, Expression e2)
5891         {
5892             super(loc, op, __traits(classInstanceSize, IdentityExp), e1, e2);
5893         }
5894 
5895         override void accept(Visitor v)
5896         {
5897             v.visit(this);
5898         }
5899     }
5900 
5901     extern (C++) final class CmpExp : BinExp
5902     {
5903         extern (D) this(TOK op, Loc loc, Expression e1, Expression e2)
5904         {
5905             super(loc, op, __traits(classInstanceSize, CmpExp), e1, e2);
5906         }
5907 
5908         override void accept(Visitor v)
5909         {
5910             v.visit(this);
5911         }
5912     }
5913 
5914     extern (C++) final class AndExp : BinExp
5915     {
5916         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5917         {
5918             super(loc, TOK.and, __traits(classInstanceSize, AndExp), e1, e2);
5919         }
5920 
5921         override void accept(Visitor v)
5922         {
5923             v.visit(this);
5924         }
5925     }
5926 
5927     extern (C++) final class XorExp : BinExp
5928     {
5929         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5930         {
5931             super(loc, TOK.xor, __traits(classInstanceSize, XorExp), e1, e2);
5932         }
5933 
5934         override void accept(Visitor v)
5935         {
5936             v.visit(this);
5937         }
5938     }
5939 
5940     extern (C++) final class OrExp : BinExp
5941     {
5942         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5943         {
5944             super(loc, TOK.or, __traits(classInstanceSize, OrExp), e1, e2);
5945         }
5946 
5947         override void accept(Visitor v)
5948         {
5949             v.visit(this);
5950         }
5951     }
5952 
5953     extern (C++) final class LogicalExp : BinExp
5954     {
5955         extern (D) this(const ref Loc loc, TOK op, Expression e1, Expression e2)
5956         {
5957             super(loc, op, __traits(classInstanceSize, LogicalExp), e1, e2);
5958         }
5959 
5960         override void accept(Visitor v)
5961         {
5962             v.visit(this);
5963         }
5964     }
5965 
5966     extern (C++) final class CondExp : BinExp
5967     {
5968         Expression econd;
5969 
5970         extern (D) this(const ref Loc loc, Expression econd, Expression e1, Expression e2)
5971         {
5972             super(loc, TOK.question, __traits(classInstanceSize, CondExp), e1, e2);
5973             this.econd = econd;
5974         }
5975 
5976         override void accept(Visitor v)
5977         {
5978             v.visit(this);
5979         }
5980     }
5981 
5982     extern (C++) final class AssignExp : BinExp
5983     {
5984         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
5985         {
5986             super(loc, TOK.assign, __traits(classInstanceSize, AssignExp), e1, e2);
5987         }
5988 
5989         override void accept(Visitor v)
5990         {
5991             v.visit(this);
5992         }
5993     }
5994 
5995     extern (C++) class BinAssignExp : BinExp
5996     {
5997         final extern (D) this(const ref Loc loc, TOK op, int size, Expression e1, Expression e2)
5998         {
5999             super(loc, op, size, e1, e2);
6000         }
6001 
6002         override void accept(Visitor v)
6003         {
6004             v.visit(this);
6005         }
6006     }
6007 
6008     extern (C++) final class AddAssignExp : BinAssignExp
6009     {
6010         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6011         {
6012             super(loc, TOK.addAssign, __traits(classInstanceSize, AddAssignExp), e1, e2);
6013         }
6014 
6015         override void accept(Visitor v)
6016         {
6017             v.visit(this);
6018         }
6019     }
6020 
6021     extern (C++) final class MinAssignExp : BinAssignExp
6022     {
6023         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6024         {
6025             super(loc, TOK.minAssign, __traits(classInstanceSize, MinAssignExp), e1, e2);
6026         }
6027 
6028         override void accept(Visitor v)
6029         {
6030             v.visit(this);
6031         }
6032     }
6033 
6034     extern (C++) final class MulAssignExp : BinAssignExp
6035     {
6036         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6037         {
6038             super(loc, TOK.mulAssign, __traits(classInstanceSize, MulAssignExp), e1, e2);
6039         }
6040 
6041         override void accept(Visitor v)
6042         {
6043             v.visit(this);
6044         }
6045     }
6046 
6047     extern (C++) final class DivAssignExp : BinAssignExp
6048     {
6049         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6050         {
6051             super(loc, TOK.divAssign, __traits(classInstanceSize, DivAssignExp), e1, e2);
6052         }
6053 
6054         override void accept(Visitor v)
6055         {
6056             v.visit(this);
6057         }
6058     }
6059 
6060     extern (C++) final class ModAssignExp : BinAssignExp
6061     {
6062         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6063         {
6064             super(loc, TOK.modAssign, __traits(classInstanceSize, ModAssignExp), e1, e2);
6065         }
6066 
6067         override void accept(Visitor v)
6068         {
6069             v.visit(this);
6070         }
6071     }
6072 
6073     extern (C++) final class PowAssignExp : BinAssignExp
6074     {
6075         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6076         {
6077             super(loc, TOK.powAssign, __traits(classInstanceSize, PowAssignExp), e1, e2);
6078         }
6079 
6080         override void accept(Visitor v)
6081         {
6082             v.visit(this);
6083         }
6084     }
6085 
6086     extern (C++) final class AndAssignExp : BinAssignExp
6087     {
6088         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6089         {
6090             super(loc, TOK.andAssign, __traits(classInstanceSize, AndAssignExp), e1, e2);
6091         }
6092 
6093         override void accept(Visitor v)
6094         {
6095             v.visit(this);
6096         }
6097     }
6098 
6099     extern (C++) final class OrAssignExp : BinAssignExp
6100     {
6101         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6102         {
6103             super(loc, TOK.orAssign, __traits(classInstanceSize, OrAssignExp), e1, e2);
6104         }
6105 
6106         override void accept(Visitor v)
6107         {
6108             v.visit(this);
6109         }
6110     }
6111 
6112     extern (C++) final class XorAssignExp : BinAssignExp
6113     {
6114         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6115         {
6116             super(loc, TOK.xorAssign, __traits(classInstanceSize, XorAssignExp), e1, e2);
6117         }
6118 
6119         override void accept(Visitor v)
6120         {
6121             v.visit(this);
6122         }
6123     }
6124 
6125     extern (C++) final class ShlAssignExp : BinAssignExp
6126     {
6127         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6128         {
6129             super(loc, TOK.leftShiftAssign, __traits(classInstanceSize, ShlAssignExp), e1, e2);
6130         }
6131 
6132         override void accept(Visitor v)
6133         {
6134             v.visit(this);
6135         }
6136     }
6137 
6138     extern (C++) final class ShrAssignExp : BinAssignExp
6139     {
6140         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6141         {
6142             super(loc, TOK.rightShiftAssign, __traits(classInstanceSize, ShrAssignExp), e1, e2);
6143         }
6144 
6145         override void accept(Visitor v)
6146         {
6147             v.visit(this);
6148         }
6149     }
6150 
6151     extern (C++) final class UshrAssignExp : BinAssignExp
6152     {
6153         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6154         {
6155             super(loc, TOK.unsignedRightShiftAssign, __traits(classInstanceSize, UshrAssignExp), e1, e2);
6156         }
6157 
6158         override void accept(Visitor v)
6159         {
6160             v.visit(this);
6161         }
6162     }
6163 
6164     extern (C++) final class CatAssignExp : BinAssignExp
6165     {
6166         extern (D) this(const ref Loc loc, Expression e1, Expression e2)
6167         {
6168             super(loc, TOK.concatenateAssign, __traits(classInstanceSize, CatAssignExp), e1, e2);
6169         }
6170 
6171         override void accept(Visitor v)
6172         {
6173             v.visit(this);
6174         }
6175     }
6176 
6177     extern (C++) class TemplateParameter : ASTNode
6178     {
6179         Loc loc;
6180         Identifier ident;
6181 
6182         final extern (D) this(const ref Loc loc, Identifier ident)
6183         {
6184             this.loc = loc;
6185             this.ident = ident;
6186         }
6187 
6188         TemplateParameter syntaxCopy(){ return null;}
6189 
6190         override void accept(Visitor v)
6191         {
6192             v.visit(this);
6193         }
6194     }
6195 
6196     extern (C++) final class TemplateAliasParameter : TemplateParameter
6197     {
6198         Type specType;
6199         RootObject specAlias;
6200         RootObject defaultAlias;
6201 
6202         extern (D) this(const ref Loc loc, Identifier ident, Type specType, RootObject specAlias, RootObject defaultAlias)
6203         {
6204             super(loc, ident);
6205             this.ident = ident;
6206             this.specType = specType;
6207             this.specAlias = specAlias;
6208             this.defaultAlias = defaultAlias;
6209         }
6210 
6211         override void accept(Visitor v)
6212         {
6213             v.visit(this);
6214         }
6215     }
6216 
6217     extern (C++) class TemplateTypeParameter : TemplateParameter
6218     {
6219         Type specType;
6220         Type defaultType;
6221 
6222         final extern (D) this(const ref Loc loc, Identifier ident, Type specType, Type defaultType)
6223         {
6224             super(loc, ident);
6225             this.ident = ident;
6226             this.specType = specType;
6227             this.defaultType = defaultType;
6228         }
6229 
6230         override void accept(Visitor v)
6231         {
6232             v.visit(this);
6233         }
6234     }
6235 
6236     extern (C++) final class TemplateTupleParameter : TemplateParameter
6237     {
6238         extern (D) this(const ref Loc loc, Identifier ident)
6239         {
6240             super(loc, ident);
6241             this.ident = ident;
6242         }
6243 
6244         override void accept(Visitor v)
6245         {
6246             v.visit(this);
6247         }
6248     }
6249 
6250     extern (C++) final class TemplateValueParameter : TemplateParameter
6251     {
6252         Type valType;
6253         Expression specValue;
6254         Expression defaultValue;
6255 
6256         extern (D) this(const ref Loc loc, Identifier ident, Type valType,
6257             Expression specValue, Expression defaultValue)
6258         {
6259             super(loc, ident);
6260             this.ident = ident;
6261             this.valType = valType;
6262             this.specValue = specValue;
6263             this.defaultValue = defaultValue;
6264         }
6265 
6266         override void accept(Visitor v)
6267         {
6268             v.visit(this);
6269         }
6270     }
6271 
6272     extern (C++) final class TemplateThisParameter : TemplateTypeParameter
6273     {
6274         extern (D) this(const ref Loc loc, Identifier ident, Type specType, Type defaultType)
6275         {
6276             super(loc, ident, specType, defaultType);
6277         }
6278 
6279         override void accept(Visitor v)
6280         {
6281             v.visit(this);
6282         }
6283     }
6284 
6285     extern (C++) abstract class Condition : ASTNode
6286     {
6287         Loc loc;
6288 
6289         final extern (D) this(const ref Loc loc)
6290         {
6291             this.loc = loc;
6292         }
6293 
6294         override void accept(Visitor v)
6295         {
6296             v.visit(this);
6297         }
6298     }
6299 
6300     extern (C++) final class StaticForeach : RootObject
6301     {
6302         Loc loc;
6303 
6304         ForeachStatement aggrfe;
6305         ForeachRangeStatement rangefe;
6306 
6307         final extern (D) this(const ref Loc loc, ForeachStatement aggrfe, ForeachRangeStatement rangefe)
6308         in
6309         {
6310             assert(!!aggrfe ^ !!rangefe);
6311         }
6312         do
6313         {
6314             this.loc = loc;
6315             this.aggrfe = aggrfe;
6316             this.rangefe = rangefe;
6317         }
6318     }
6319 
6320     extern (C++) final class StaticIfCondition : Condition
6321     {
6322         Expression exp;
6323 
6324         final extern (D) this(const ref Loc loc, Expression exp)
6325         {
6326             super(loc);
6327             this.exp = exp;
6328         }
6329 
6330         override void accept(Visitor v)
6331         {
6332             v.visit(this);
6333         }
6334     }
6335 
6336     extern (C++) class DVCondition : Condition
6337     {
6338         uint level;
6339         Identifier ident;
6340         Module mod;
6341 
6342         final extern (D) this(Module mod, uint level, Identifier ident)
6343         {
6344             super(Loc.initial);
6345             this.mod = mod;
6346             this.ident = ident;
6347         }
6348 
6349         override void accept(Visitor v)
6350         {
6351             v.visit(this);
6352         }
6353     }
6354 
6355     extern (C++) final class DebugCondition : DVCondition
6356     {
6357         extern (D) this(Module mod, uint level, Identifier ident)
6358         {
6359             super(mod, level, ident);
6360         }
6361 
6362         override void accept(Visitor v)
6363         {
6364             v.visit(this);
6365         }
6366     }
6367 
6368     extern (C++) final class VersionCondition : DVCondition
6369     {
6370         extern (D) this(Module mod, uint level, Identifier ident)
6371         {
6372             super(mod, level, ident);
6373         }
6374 
6375         override void accept(Visitor v)
6376         {
6377             v.visit(this);
6378         }
6379     }
6380 
6381     enum InitKind : ubyte
6382     {
6383         void_,
6384         error,
6385         struct_,
6386         array,
6387         exp,
6388     }
6389 
6390     extern (C++) class Initializer : ASTNode
6391     {
6392         Loc loc;
6393         InitKind kind;
6394 
6395         final extern (D) this(const ref Loc loc, InitKind kind)
6396         {
6397             this.loc = loc;
6398             this.kind = kind;
6399         }
6400 
6401         // this should be abstract and implemented in child classes
6402         Expression toExpression(Type t = null)
6403         {
6404             return null;
6405         }
6406 
6407         final ExpInitializer isExpInitializer()
6408         {
6409             return kind == InitKind.exp ? cast(ExpInitializer)cast(void*)this : null;
6410         }
6411 
6412         override void accept(Visitor v)
6413         {
6414             v.visit(this);
6415         }
6416     }
6417 
6418     extern (C++) final class ExpInitializer : Initializer
6419     {
6420         Expression exp;
6421 
6422         extern (D) this(const ref Loc loc, Expression exp)
6423         {
6424             super(loc, InitKind.exp);
6425             this.exp = exp;
6426         }
6427 
6428         override void accept(Visitor v)
6429         {
6430             v.visit(this);
6431         }
6432     }
6433 
6434     extern (C++) final class StructInitializer : Initializer
6435     {
6436         Identifiers field;
6437         Initializers value;
6438 
6439         extern (D) this(const ref Loc loc)
6440         {
6441             super(loc, InitKind.struct_);
6442         }
6443 
6444         void addInit(Identifier field, Initializer value)
6445         {
6446             this.field.push(field);
6447             this.value.push(value);
6448         }
6449 
6450         override void accept(Visitor v)
6451         {
6452             v.visit(this);
6453         }
6454     }
6455 
6456     extern (C++) final class ArrayInitializer : Initializer
6457     {
6458         Expressions index;
6459         Initializers value;
6460         uint dim;
6461         Type type;
6462 
6463         extern (D) this(const ref Loc loc)
6464         {
6465             super(loc, InitKind.array);
6466         }
6467 
6468         void addInit(Expression index, Initializer value)
6469         {
6470             this.index.push(index);
6471             this.value.push(value);
6472             dim = 0;
6473             type = null;
6474         }
6475 
6476         override void accept(Visitor v)
6477         {
6478             v.visit(this);
6479         }
6480     }
6481 
6482     extern (C++) final class VoidInitializer : Initializer
6483     {
6484         extern (D) this(const ref Loc loc)
6485         {
6486             super(loc, InitKind.void_);
6487         }
6488 
6489         override void accept(Visitor v)
6490         {
6491             v.visit(this);
6492         }
6493     }
6494 
6495     extern (C++) final class Tuple : RootObject
6496     {
6497         Objects objects;
6498 
6499         // kludge for template.isType()
6500         override DYNCAST dyncast() const
6501         {
6502             return DYNCAST.tuple;
6503         }
6504 
6505         override const(char)* toChars() const
6506         {
6507             return objects.toChars();
6508         }
6509     }
6510 
6511     struct BaseClass
6512     {
6513         Type type;
6514     }
6515 
6516     struct ModuleDeclaration
6517     {
6518         Loc loc;
6519         Identifier id;
6520         Identifiers *packages;
6521         bool isdeprecated;
6522         Expression msg;
6523 
6524         extern (D) this(const ref Loc loc, Identifiers* packages, Identifier id, Expression msg, bool isdeprecated)
6525         {
6526             this.loc = loc;
6527             this.packages = packages;
6528             this.id = id;
6529             this.msg = msg;
6530             this.isdeprecated = isdeprecated;
6531         }
6532 
6533         extern (C++) const(char)* toChars() const
6534         {
6535             OutBuffer buf;
6536             if (packages && packages.dim)
6537             {
6538                 for (size_t i = 0; i < packages.dim; i++)
6539                 {
6540                     const Identifier pid = (*packages)[i];
6541                     buf.writestring(pid.toString());
6542                     buf.writeByte('.');
6543                 }
6544             }
6545             buf.writestring(id.toString());
6546             return buf.extractChars();
6547         }
6548     }
6549 
6550     struct Prot
6551     {
6552         enum Kind : int
6553         {
6554             undefined,
6555             none,
6556             private_,
6557             package_,
6558             protected_,
6559             public_,
6560             export_,
6561         }
6562         Kind kind;
6563         Package pkg;
6564     }
6565 
6566     struct Scope
6567     {
6568 
6569     }
6570 
6571     static extern (C++) Tuple isTuple(RootObject o)
6572     {
6573         //return dynamic_cast<Tuple *>(o);
6574         if (!o || o.dyncast() != DYNCAST.tuple)
6575             return null;
6576         return cast(Tuple)o;
6577     }
6578 
6579     static extern (C++) Type isType(RootObject o)
6580     {
6581         if (!o || o.dyncast() != DYNCAST.type)
6582             return null;
6583         return cast(Type)o;
6584     }
6585 
6586     static extern (C++) Expression isExpression(RootObject o)
6587     {
6588         if (!o || o.dyncast() != DYNCAST.expression)
6589             return null;
6590         return cast(Expression)o;
6591     }
6592 
6593     static extern (C++) TemplateParameter isTemplateParameter(RootObject o)
6594     {
6595         if (!o || o.dyncast() != DYNCAST.templateparameter)
6596             return null;
6597         return cast(TemplateParameter)o;
6598     }
6599 
6600 
6601     static const(char)* protectionToChars(Prot.Kind kind)
6602     {
6603         final switch (kind)
6604         {
6605         case Prot.Kind.undefined:
6606             return null;
6607         case Prot.Kind.none:
6608             return "none";
6609         case Prot.Kind.private_:
6610             return "private";
6611         case Prot.Kind.package_:
6612             return "package";
6613         case Prot.Kind.protected_:
6614             return "protected";
6615         case Prot.Kind.public_:
6616             return "public";
6617         case Prot.Kind.export_:
6618             return "export";
6619         }
6620     }
6621 
6622     static bool stcToBuffer(OutBuffer* buf, StorageClass stc)
6623     {
6624         bool result = false;
6625         if ((stc & (STC.return_ | STC.scope_)) == (STC.return_ | STC.scope_))
6626             stc &= ~STC.scope_;
6627         while (stc)
6628         {
6629             const(char)* p = stcToChars(stc);
6630             if (!p) // there's no visible storage classes
6631                 break;
6632             if (!result)
6633                 result = true;
6634             else
6635                 buf.writeByte(' ');
6636             buf.writestring(p);
6637         }
6638         return result;
6639     }
6640 
6641     static extern (C++) Expression typeToExpression(Type t)
6642     {
6643         return t.toExpression;
6644     }
6645 
6646     static const(char)* stcToChars(ref StorageClass stc)
6647     {
6648         struct SCstring
6649         {
6650             StorageClass stc;
6651             TOK tok;
6652             const(char)* id;
6653         }
6654 
6655         __gshared SCstring* table =
6656         [
6657             SCstring(STC.auto_, TOK.auto_),
6658             SCstring(STC.scope_, TOK.scope_),
6659             SCstring(STC.static_, TOK.static_),
6660             SCstring(STC.extern_, TOK.extern_),
6661             SCstring(STC.const_, TOK.const_),
6662             SCstring(STC.final_, TOK.final_),
6663             SCstring(STC.abstract_, TOK.abstract_),
6664             SCstring(STC.synchronized_, TOK.synchronized_),
6665             SCstring(STC.deprecated_, TOK.deprecated_),
6666             SCstring(STC.override_, TOK.override_),
6667             SCstring(STC.lazy_, TOK.lazy_),
6668             SCstring(STC.alias_, TOK.alias_),
6669             SCstring(STC.out_, TOK.out_),
6670             SCstring(STC.in_, TOK.in_),
6671             SCstring(STC.manifest, TOK.enum_),
6672             SCstring(STC.immutable_, TOK.immutable_),
6673             SCstring(STC.shared_, TOK.shared_),
6674             SCstring(STC.nothrow_, TOK.nothrow_),
6675             SCstring(STC.wild, TOK.inout_),
6676             SCstring(STC.pure_, TOK.pure_),
6677             SCstring(STC.ref_, TOK.ref_),
6678             SCstring(STC.tls),
6679             SCstring(STC.gshared, TOK.gshared),
6680             SCstring(STC.nogc, TOK.at, "@nogc"),
6681             SCstring(STC.property, TOK.at, "@property"),
6682             SCstring(STC.safe, TOK.at, "@safe"),
6683             SCstring(STC.trusted, TOK.at, "@trusted"),
6684             SCstring(STC.system, TOK.at, "@system"),
6685             SCstring(STC.live, TOK.at, "@live"),
6686             SCstring(STC.disable, TOK.at, "@disable"),
6687             SCstring(STC.future, TOK.at, "@__future"),
6688             SCstring(0, TOK.reserved)
6689         ];
6690         for (int i = 0; table[i].stc; i++)
6691         {
6692             StorageClass tbl = table[i].stc;
6693             assert(tbl & STCStorageClass);
6694             if (stc & tbl)
6695             {
6696                 stc &= ~tbl;
6697                 if (tbl == STC.tls) // TOKtls was removed
6698                     return "__thread";
6699                 TOK tok = table[i].tok;
6700                 if (tok == TOK.at)
6701                     return table[i].id;
6702                 else
6703                     return Token.toChars(tok);
6704             }
6705         }
6706         //printf("stc = %llx\n", stc);
6707         return null;
6708     }
6709 
6710     static const(char)* linkageToChars(LINK linkage)
6711     {
6712         final switch (linkage)
6713         {
6714         case LINK.default_:
6715         case LINK.system:
6716             return null;
6717         case LINK.d:
6718             return "D";
6719         case LINK.c:
6720             return "C";
6721         case LINK.cpp:
6722             return "C++";
6723         case LINK.windows:
6724             return "Windows";
6725         case LINK.pascal:
6726             return "Pascal";
6727         case LINK.objc:
6728             return "Objective-C";
6729         }
6730     }
6731 
6732     struct Target
6733     {
6734         extern (C++) __gshared int ptrsize;
6735 
6736         extern (C++) static Type va_listType(const ref Loc loc, Scope* sc)
6737         {
6738             if (global.params.isWindows)
6739             {
6740                 return Type.tchar.pointerTo();
6741             }
6742             else if (global.params.isLinux || global.params.isFreeBSD || global.params.isOpenBSD  || global.params.isDragonFlyBSD ||
6743                 global.params.isSolaris || global.params.isOSX)
6744             {
6745                 if (global.params.is64bit)
6746                 {
6747                     return (new TypeIdentifier(Loc.initial, Identifier.idPool("__va_list_tag"))).pointerTo();
6748                 }
6749                 else
6750                 {
6751                     return Type.tchar.pointerTo();
6752                 }
6753             }
6754             else
6755             {
6756                 assert(0);
6757             }
6758         }
6759     }
6760 }