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