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