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