1 /**
2  * Documentation:  https://dlang.org/phobos/dmd_transitivevisitor.html
3  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/transitivevisitor.d
4  */
5 
6 module dmd.transitivevisitor;
7 
8 import dmd.permissivevisitor;
9 import dmd.tokens;
10 import dmd.root.rootobject;
11 
12 import core.stdc.stdio;
13 
14 /** Visitor that implements the AST traversal logic. The nodes just accept their children.
15   */
16 extern(C++) class ParseTimeTransitiveVisitor(AST) : PermissiveVisitor!AST
17 {
18     alias visit = PermissiveVisitor!AST.visit;
19     mixin ParseVisitMethods!AST;
20 }
21 
22 /* This mixin implements the AST traversal logic for parse time AST nodes. The same code
23  * is used for semantic time AST node traversal, so in order to not duplicate the code,
24  * the template mixin is used.
25  */
26 package mixin template ParseVisitMethods(AST)
27 {
28 
29 //   Statement Nodes
30 //===========================================================
31     override void visit(AST.ExpStatement s)
32     {
33         //printf("Visiting ExpStatement\n");
34         if (s.exp && s.exp.op == TOK.declaration)
35         {
36             (cast(AST.DeclarationExp)s.exp).declaration.accept(this);
37             return;
38         }
39         if (s.exp)
40             s.exp.accept(this);
41     }
42 
43     override void visit(AST.CompileStatement s)
44     {
45         //printf("Visiting CompileStatement\n");
46         visitArgs(s.exps);
47     }
48 
49     override void visit(AST.CompoundStatement s)
50     {
51         //printf("Visiting CompoundStatement\n");
52         foreach (sx; *s.statements)
53         {
54             if (sx)
55                 sx.accept(this);
56         }
57     }
58 
59     void visitVarDecl(AST.VarDeclaration v)
60     {
61         //printf("Visiting VarDeclaration\n");
62         if (v.type)
63             visitType(v.type);
64         if (v._init)
65         {
66             auto ie = v._init.isExpInitializer();
67             if (ie && (ie.exp.op == TOK.construct || ie.exp.op == TOK.blit))
68                 (cast(AST.AssignExp)ie.exp).e2.accept(this);
69             else
70                 v._init.accept(this);
71         }
72     }
73 
74     override void visit(AST.CompoundDeclarationStatement s)
75     {
76         //printf("Visiting CompoundDeclarationStatement\n");
77         foreach (sx; *s.statements)
78         {
79             auto ds = sx ? sx.isExpStatement() : null;
80             if (ds && ds.exp.op == TOK.declaration)
81             {
82                 auto d = (cast(AST.DeclarationExp)ds.exp).declaration;
83                 assert(d.isDeclaration());
84                 if (auto v = d.isVarDeclaration())
85                     visitVarDecl(v);
86                 else
87                     d.accept(this);
88             }
89         }
90     }
91 
92     override void visit(AST.ScopeStatement s)
93     {
94         //printf("Visiting ScopeStatement\n");
95         if (s.statement)
96             s.statement.accept(this);
97     }
98 
99     override void visit(AST.WhileStatement s)
100     {
101         //printf("Visiting WhileStatement\n");
102         s.condition.accept(this);
103         if (s._body)
104             s._body.accept(this);
105     }
106 
107     override void visit(AST.DoStatement s)
108     {
109         //printf("Visiting DoStatement\n");
110         if (s._body)
111             s._body.accept(this);
112         s.condition.accept(this);
113     }
114 
115     override void visit(AST.ForStatement s)
116     {
117         //printf("Visiting ForStatement\n");
118         if (s._init)
119             s._init.accept(this);
120         if (s.condition)
121             s.condition.accept(this);
122         if (s.increment)
123             s.increment.accept(this);
124         if (s._body)
125             s._body.accept(this);
126     }
127 
128     override void visit(AST.ForeachStatement s)
129     {
130         //printf("Visiting ForeachStatement\n");
131         foreach (p; *s.parameters)
132             if (p.type)
133                 visitType(p.type);
134         s.aggr.accept(this);
135         if (s._body)
136             s._body.accept(this);
137     }
138 
139     override void visit(AST.ForeachRangeStatement s)
140     {
141         //printf("Visiting ForeachRangeStatement\n");
142         if (s.prm.type)
143             visitType(s.prm.type);
144         s.lwr.accept(this);
145         s.upr.accept(this);
146         if (s._body)
147             s._body.accept(this);
148     }
149 
150     override void visit(AST.IfStatement s)
151     {
152         //printf("Visiting IfStatement\n");
153         if (s.prm && s.prm.type)
154             visitType(s.prm.type);
155         s.condition.accept(this);
156         s.ifbody.accept(this);
157         if (s.elsebody)
158             s.elsebody.accept(this);
159     }
160 
161     override void visit(AST.ConditionalStatement s)
162     {
163         //printf("Visiting ConditionalStatement\n");
164         s.condition.accept(this);
165         if (s.ifbody)
166             s.ifbody.accept(this);
167         if (s.elsebody)
168             s.elsebody.accept(this);
169     }
170 
171     void visitArgs(AST.Expressions* expressions, AST.Expression basis = null)
172     {
173         if (!expressions || !expressions.dim)
174             return;
175         foreach (el; *expressions)
176         {
177             if (!el)
178                 el = basis;
179             if (el)
180                 el.accept(this);
181         }
182     }
183 
184     override void visit(AST.PragmaStatement s)
185     {
186         //printf("Visiting PragmaStatement\n");
187         if (s.args && s.args.dim)
188             visitArgs(s.args);
189         if (s._body)
190             s._body.accept(this);
191     }
192 
193     override void visit(AST.StaticAssertStatement s)
194     {
195         //printf("Visiting StaticAssertStatement\n");
196         s.sa.accept(this);
197     }
198 
199     override void visit(AST.SwitchStatement s)
200     {
201         //printf("Visiting SwitchStatement\n");
202         s.condition.accept(this);
203         if (s._body)
204             s._body.accept(this);
205     }
206 
207     override void visit(AST.CaseStatement s)
208     {
209         //printf("Visiting CaseStatement\n");
210         s.exp.accept(this);
211         s.statement.accept(this);
212     }
213 
214     override void visit(AST.CaseRangeStatement s)
215     {
216         //printf("Visiting CaseRangeStatement\n");
217         s.first.accept(this);
218         s.last.accept(this);
219         s.statement.accept(this);
220     }
221 
222     override void visit(AST.DefaultStatement s)
223     {
224         //printf("Visiting DefaultStatement\n");
225         s.statement.accept(this);
226     }
227 
228     override void visit(AST.GotoCaseStatement s)
229     {
230         //printf("Visiting GotoCaseStatement\n");
231         if (s.exp)
232             s.exp.accept(this);
233     }
234 
235     override void visit(AST.ReturnStatement s)
236     {
237         //printf("Visiting ReturnStatement\n");
238         if (s.exp)
239             s.exp.accept(this);
240     }
241 
242     override void visit(AST.SynchronizedStatement s)
243     {
244         //printf("Visiting SynchronizedStatement\n");
245         if (s.exp)
246             s.exp.accept(this);
247         if (s._body)
248             s._body.accept(this);
249     }
250 
251     override void visit(AST.WithStatement s)
252     {
253         //printf("Visiting WithStatement\n");
254         s.exp.accept(this);
255         if (s._body)
256             s._body.accept(this);
257     }
258 
259     override void visit(AST.TryCatchStatement s)
260     {
261         //printf("Visiting TryCatchStatement\n");
262         if (s._body)
263             s._body.accept(this);
264         foreach (c; *s.catches)
265             visit(c);
266     }
267 
268     override void visit(AST.TryFinallyStatement s)
269     {
270         //printf("Visiting TryFinallyStatement\n");
271         s._body.accept(this);
272         s.finalbody.accept(this);
273     }
274 
275     override void visit(AST.ScopeGuardStatement s)
276     {
277         //printf("Visiting ScopeGuardStatement\n");
278         s.statement.accept(this);
279     }
280 
281     override void visit(AST.ThrowStatement s)
282     {
283         //printf("Visiting ThrowStatement\n");
284         s.exp.accept(this);
285     }
286 
287     override void visit(AST.LabelStatement s)
288     {
289         //printf("Visiting LabelStatement\n");
290         if (s.statement)
291             s.statement.accept(this);
292     }
293 
294     override void visit(AST.ImportStatement s)
295     {
296         //printf("Visiting ImportStatement\n");
297         foreach (imp; *s.imports)
298             imp.accept(this);
299     }
300 
301     void visit(AST.Catch c)
302     {
303         //printf("Visiting Catch\n");
304         if (c.type)
305             visitType(c.type);
306         if (c.handler)
307             c.handler.accept(this);
308     }
309 
310 //   Type Nodes
311 //============================================================
312 
313     void visitType(AST.Type t)
314     {
315         //printf("Visiting Type\n");
316         if (!t)
317             return;
318         if (t.ty == AST.Tfunction)
319         {
320             visitFunctionType(cast(AST.TypeFunction)t, null);
321             return;
322         }
323         else
324             t.accept(this);
325     }
326 
327     void visitFunctionType(AST.TypeFunction t, AST.TemplateDeclaration td)
328     {
329         if (t.next)
330             visitType(t.next);
331         if (td)
332         {
333             foreach (p; *td.origParameters)
334                 p.accept(this);
335         }
336         visitParameters(t.parameterList.parameters);
337     }
338 
339     void visitParameters(AST.Parameters* parameters)
340     {
341         if (parameters)
342         {
343             size_t dim = AST.Parameter.dim(parameters);
344             foreach(i; 0..dim)
345             {
346                 AST.Parameter fparam = AST.Parameter.getNth(parameters, i);
347                 fparam.accept(this);
348             }
349         }
350     }
351 
352     override void visit(AST.TypeVector t)
353     {
354         //printf("Visiting TypeVector\n");
355         if (!t.basetype)
356             return;
357         t.basetype.accept(this);
358     }
359 
360     override void visit(AST.TypeSArray t)
361     {
362         //printf("Visiting TypeSArray\n");
363         t.next.accept(this);
364     }
365 
366     override void visit(AST.TypeDArray t)
367     {
368         //printf("Visiting TypeDArray\n");
369         t.next.accept(this);
370     }
371 
372     override void visit(AST.TypeAArray t)
373     {
374         //printf("Visiting TypeAArray\n");
375         t.next.accept(this);
376         t.index.accept(this);
377     }
378 
379     override void visit(AST.TypePointer t)
380     {
381         //printf("Visiting TypePointer\n");
382         if (t.next.ty == AST.Tfunction)
383         {
384             visitFunctionType(cast(AST.TypeFunction)t.next, null);
385         }
386         else
387             t.next.accept(this);
388     }
389 
390     override void visit(AST.TypeReference t)
391     {
392         //printf("Visiting TypeReference\n");
393         t.next.accept(this);
394     }
395 
396     override void visit(AST.TypeFunction t)
397     {
398         //printf("Visiting TypeFunction\n");
399         visitFunctionType(t, null);
400     }
401 
402     override void visit(AST.TypeDelegate t)
403     {
404         //printf("Visiting TypeDelegate\n");
405         visitFunctionType(cast(AST.TypeFunction)t.next, null);
406     }
407 
408     void visitTypeQualified(AST.TypeQualified t)
409     {
410         //printf("Visiting TypeQualified\n");
411         foreach (id; t.idents)
412         {
413             if (id.dyncast() == DYNCAST.dsymbol)
414                 (cast(AST.TemplateInstance)id).accept(this);
415             else if (id.dyncast() == DYNCAST.expression)
416                 (cast(AST.Expression)id).accept(this);
417             else if (id.dyncast() == DYNCAST.type)
418                 (cast(AST.Type)id).accept(this);
419         }
420     }
421 
422     override void visit(AST.TypeIdentifier t)
423     {
424         //printf("Visiting TypeIdentifier\n");
425         visitTypeQualified(t);
426     }
427 
428     override void visit(AST.TypeInstance t)
429     {
430         //printf("Visiting TypeInstance\n");
431         t.tempinst.accept(this);
432         visitTypeQualified(t);
433     }
434 
435     override void visit(AST.TypeTypeof t)
436     {
437         //printf("Visiting TypeTypeof\n");
438         t.exp.accept(this);
439         visitTypeQualified(t);
440     }
441 
442     override void visit(AST.TypeReturn t)
443     {
444         //printf("Visiting TypeReturn\n");
445         visitTypeQualified(t);
446     }
447 
448     override void visit(AST.TypeTuple t)
449     {
450         //printf("Visiting TypeTuple\n");
451         visitParameters(t.arguments);
452     }
453 
454     override void visit(AST.TypeSlice t)
455     {
456         //printf("Visiting TypeSlice\n");
457         t.next.accept(this);
458         t.lwr.accept(this);
459         t.upr.accept(this);
460     }
461 
462     override void visit(AST.TypeTraits t)
463     {
464         t.exp.accept(this);
465     }
466 
467 //      Miscellaneous
468 //========================================================
469 
470     override void visit(AST.StaticAssert s)
471     {
472         //printf("Visiting StaticAssert\n");
473         s.exp.accept(this);
474         if (s.msg)
475             s.msg.accept(this);
476     }
477 
478     override void visit(AST.EnumMember em)
479     {
480         //printf("Visiting EnumMember\n");
481         if (em.type)
482             visitType(em.type);
483         if (em.value)
484             em.value.accept(this);
485     }
486 
487 //      Declarations
488 //=========================================================
489     void visitAttribDeclaration(AST.AttribDeclaration d)
490     {
491         if (d.decl)
492             foreach (de; *d.decl)
493                 de.accept(this);
494     }
495 
496     override void visit(AST.AttribDeclaration d)
497     {
498         //printf("Visiting AttribDeclaration\n");
499         visitAttribDeclaration(d);
500     }
501 
502     override void visit(AST.StorageClassDeclaration d)
503     {
504         //printf("Visiting StorageClassDeclaration\n");
505         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
506     }
507 
508     override void visit(AST.DeprecatedDeclaration d)
509     {
510         //printf("Visiting DeprecatedDeclaration\n");
511         d.msg.accept(this);
512         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
513     }
514 
515     override void visit(AST.LinkDeclaration d)
516     {
517         //printf("Visiting LinkDeclaration\n");
518         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
519     }
520 
521     override void visit(AST.CPPMangleDeclaration d)
522     {
523         //printf("Visiting CPPMangleDeclaration\n");
524         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
525     }
526 
527     override void visit(AST.ProtDeclaration d)
528     {
529         //printf("Visiting ProtDeclaration\n");
530         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
531     }
532 
533     override void visit(AST.AlignDeclaration d)
534     {
535         //printf("Visiting AlignDeclaration\n");
536         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
537     }
538 
539     override void visit(AST.AnonDeclaration d)
540     {
541         //printf("Visiting AnonDeclaration\n");
542         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
543     }
544 
545     override void visit(AST.PragmaDeclaration d)
546     {
547         //printf("Visiting PragmaDeclaration\n");
548         if (d.args && d.args.dim)
549             visitArgs(d.args);
550         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
551     }
552 
553     override void visit(AST.ConditionalDeclaration d)
554     {
555         //printf("Visiting ConditionalDeclaration\n");
556         d.condition.accept(this);
557         if (d.decl)
558             foreach (de; *d.decl)
559                 de.accept(this);
560         if (d.elsedecl)
561             foreach (de; *d.elsedecl)
562                 de.accept(this);
563     }
564 
565     override void visit(AST.CompileDeclaration d)
566     {
567         //printf("Visiting compileDeclaration\n");
568         visitArgs(d.exps);
569     }
570 
571     override void visit(AST.UserAttributeDeclaration d)
572     {
573         //printf("Visiting UserAttributeDeclaration\n");
574         visitArgs(d.atts);
575         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
576     }
577 
578     void visitFuncBody(AST.FuncDeclaration f)
579     {
580         //printf("Visiting funcBody\n");
581         if (f.frequires)
582         {
583             foreach (frequire; *f.frequires)
584             {
585                 frequire.accept(this);
586             }
587         }
588         if (f.fensures)
589         {
590             foreach (fensure; *f.fensures)
591             {
592                 fensure.ensure.accept(this);
593             }
594         }
595         if (f.fbody)
596         {
597             f.fbody.accept(this);
598         }
599     }
600 
601     void visitBaseClasses(AST.ClassDeclaration d)
602     {
603         //printf("Visiting ClassDeclaration\n");
604         if (!d || !d.baseclasses.dim)
605             return;
606         foreach (b; *d.baseclasses)
607             visitType(b.type);
608     }
609 
610     bool visitEponymousMember(AST.TemplateDeclaration d)
611     {
612         //printf("Visiting EponymousMember\n");
613         if (!d.members || d.members.dim != 1)
614             return false;
615         AST.Dsymbol onemember = (*d.members)[0];
616         if (onemember.ident != d.ident)
617             return false;
618 
619         if (AST.FuncDeclaration fd = onemember.isFuncDeclaration())
620         {
621             assert(fd.type);
622             visitFunctionType(cast(AST.TypeFunction)fd.type, d);
623             if (d.constraint)
624                 d.constraint.accept(this);
625             visitFuncBody(fd);
626 
627             return true;
628         }
629 
630         if (AST.AggregateDeclaration ad = onemember.isAggregateDeclaration())
631         {
632             visitTemplateParameters(d.parameters);
633             if (d.constraint)
634                 d.constraint.accept(this);
635             visitBaseClasses(ad.isClassDeclaration());
636 
637             if (ad.members)
638                 foreach (s; *ad.members)
639                     s.accept(this);
640 
641             return true;
642         }
643 
644         if (AST.VarDeclaration vd = onemember.isVarDeclaration())
645         {
646             if (d.constraint)
647                 return false;
648             if (vd.type)
649                 visitType(vd.type);
650             visitTemplateParameters(d.parameters);
651             if (vd._init)
652             {
653                 AST.ExpInitializer ie = vd._init.isExpInitializer();
654                 if (ie && (ie.exp.op == TOK.construct || ie.exp.op == TOK.blit))
655                     (cast(AST.AssignExp)ie.exp).e2.accept(this);
656                 else
657                     vd._init.accept(this);
658 
659                 return true;
660             }
661         }
662 
663         return false;
664     }
665 
666     void visitTemplateParameters(AST.TemplateParameters* parameters)
667     {
668         if (!parameters || !parameters.dim)
669             return;
670         foreach (p; *parameters)
671             p.accept(this);
672     }
673 
674     override void visit(AST.TemplateDeclaration d)
675     {
676         //printf("Visiting TemplateDeclaration\n");
677         if (visitEponymousMember(d))
678             return;
679 
680         visitTemplateParameters(d.parameters);
681         if (d.constraint)
682             d.constraint.accept(this);
683 
684         foreach (s; *d.members)
685             s.accept(this);
686     }
687 
688     void visitObject(RootObject oarg)
689     {
690         if (auto t = AST.isType(oarg))
691         {
692             visitType(t);
693         }
694         else if (auto e = AST.isExpression(oarg))
695         {
696             e.accept(this);
697         }
698         else if (auto v = AST.isTuple(oarg))
699         {
700             auto args = &v.objects;
701             foreach (arg; *args)
702                 visitObject(arg);
703         }
704     }
705 
706     void visitTiargs(AST.TemplateInstance ti)
707     {
708         //printf("Visiting tiargs\n");
709         if (!ti.tiargs)
710             return;
711         foreach (arg; *ti.tiargs)
712         {
713             visitObject(arg);
714         }
715     }
716 
717     override void visit(AST.TemplateInstance ti)
718     {
719         //printf("Visiting TemplateInstance\n");
720         visitTiargs(ti);
721     }
722 
723     override void visit(AST.TemplateMixin tm)
724     {
725         //printf("Visiting TemplateMixin\n");
726         visitType(tm.tqual);
727         visitTiargs(tm);
728     }
729 
730     override void visit(AST.EnumDeclaration d)
731     {
732         //printf("Visiting EnumDeclaration\n");
733         if (d.memtype)
734             visitType(d.memtype);
735         if (!d.members)
736             return;
737         foreach (em; *d.members)
738         {
739             if (!em)
740                 continue;
741             em.accept(this);
742         }
743     }
744 
745     override void visit(AST.Nspace d)
746     {
747         //printf("Visiting Nspace\n");
748         foreach(s; *d.members)
749             s.accept(this);
750     }
751 
752     override void visit(AST.StructDeclaration d)
753     {
754         //printf("Visiting StructDeclaration\n");
755         if (!d.members)
756             return;
757         foreach (s; *d.members)
758             s.accept(this);
759     }
760 
761     override void visit(AST.ClassDeclaration d)
762     {
763         //printf("Visiting ClassDeclaration\n");
764         visitBaseClasses(d);
765         if (d.members)
766             foreach (s; *d.members)
767                 s.accept(this);
768     }
769 
770     override void visit(AST.AliasDeclaration d)
771     {
772         //printf("Visting AliasDeclaration\n");
773         if (d.aliassym)
774             d.aliassym.accept(this);
775         else
776             visitType(d.type);
777     }
778 
779     override void visit(AST.VarDeclaration d)
780     {
781         //printf("Visiting VarDeclaration\n");
782         visitVarDecl(d);
783     }
784 
785     override void visit(AST.FuncDeclaration f)
786     {
787         //printf("Visiting FuncDeclaration\n");
788         auto tf = cast(AST.TypeFunction)f.type;
789         visitType(tf);
790         visitFuncBody(f);
791     }
792 
793     override void visit(AST.FuncLiteralDeclaration f)
794     {
795         //printf("Visiting FuncLiteralDeclaration\n");
796         if (f.type.ty == AST.Terror)
797             return;
798         AST.TypeFunction tf = cast(AST.TypeFunction)f.type;
799         if (!f.inferRetType && tf.next)
800             visitType(tf.next);
801         visitParameters(tf.parameterList.parameters);
802         AST.CompoundStatement cs = f.fbody.isCompoundStatement();
803         AST.Statement s = !cs ? f.fbody : null;
804         AST.ReturnStatement rs = s ? s.isReturnStatement() : null;
805         if (rs && rs.exp)
806             rs.exp.accept(this);
807         else
808             visitFuncBody(f);
809     }
810 
811     override void visit(AST.PostBlitDeclaration d)
812     {
813         //printf("Visiting PostBlitDeclaration\n");
814         visitFuncBody(d);
815     }
816 
817     override void visit(AST.DtorDeclaration d)
818     {
819         //printf("Visiting DtorDeclaration\n");
820         visitFuncBody(d);
821     }
822 
823     override void visit(AST.StaticCtorDeclaration d)
824     {
825         //printf("Visiting StaticCtorDeclaration\n");
826         visitFuncBody(d);
827     }
828 
829     override void visit(AST.StaticDtorDeclaration d)
830     {
831         //printf("Visiting StaticDtorDeclaration\n");
832         visitFuncBody(d);
833     }
834 
835     override void visit(AST.InvariantDeclaration d)
836     {
837         //printf("Visiting InvariantDeclaration\n");
838         visitFuncBody(d);
839     }
840 
841     override void visit(AST.UnitTestDeclaration d)
842     {
843         //printf("Visiting UnitTestDeclaration\n");
844         visitFuncBody(d);
845     }
846 
847     override void visit(AST.NewDeclaration d)
848     {
849         //printf("Visiting NewDeclaration\n");
850         visitParameters(d.parameters);
851         visitFuncBody(d);
852     }
853 
854 //   Initializers
855 //============================================================
856 
857     override void visit(AST.StructInitializer si)
858     {
859         //printf("Visiting StructInitializer\n");
860         foreach (i, const id; si.field)
861             if (auto iz = si.value[i])
862                 iz.accept(this);
863     }
864 
865     override void visit(AST.ArrayInitializer ai)
866     {
867         //printf("Visiting ArrayInitializer\n");
868         foreach (i, ex; ai.index)
869         {
870             if (ex)
871                 ex.accept(this);
872             if (auto iz = ai.value[i])
873                 iz.accept(this);
874         }
875     }
876 
877     override void visit(AST.ExpInitializer ei)
878     {
879         //printf("Visiting ExpInitializer\n");
880         ei.exp.accept(this);
881     }
882 
883 //      Expressions
884 //===================================================
885 
886     override void visit(AST.ArrayLiteralExp e)
887     {
888         //printf("Visiting ArrayLiteralExp\n");
889         visitArgs(e.elements, e.basis);
890     }
891 
892     override void visit(AST.AssocArrayLiteralExp e)
893     {
894         //printf("Visiting AssocArrayLiteralExp\n");
895         foreach (i, key; *e.keys)
896         {
897             key.accept(this);
898             ((*e.values)[i]).accept(this);
899         }
900     }
901 
902     override void visit(AST.TypeExp e)
903     {
904         //printf("Visiting TypeExp\n");
905         visitType(e.type);
906     }
907 
908     override void visit(AST.ScopeExp e)
909     {
910         //printf("Visiting ScopeExp\n");
911         if (e.sds.isTemplateInstance())
912             e.sds.accept(this);
913     }
914 
915     override void visit(AST.NewExp e)
916     {
917         //printf("Visiting NewExp\n");
918         if (e.thisexp)
919             e.thisexp.accept(this);
920         if (e.newargs && e.newargs.dim)
921             visitArgs(e.newargs);
922         visitType(e.newtype);
923         if (e.arguments && e.arguments.dim)
924             visitArgs(e.arguments);
925     }
926 
927     override void visit(AST.NewAnonClassExp e)
928     {
929         //printf("Visiting NewAnonClassExp\n");
930         if (e.thisexp)
931             e.thisexp.accept(this);
932         if (e.newargs && e.newargs.dim)
933             visitArgs(e.newargs);
934         if (e.arguments && e.arguments.dim)
935             visitArgs(e.arguments);
936         if (e.cd)
937             e.cd.accept(this);
938     }
939 
940     override void visit(AST.TupleExp e)
941     {
942         //printf("Visiting TupleExp\n");
943         if (e.e0)
944             e.e0.accept(this);
945         visitArgs(e.exps);
946     }
947 
948     override void visit(AST.FuncExp e)
949     {
950         //printf("Visiting FuncExp\n");
951         e.fd.accept(this);
952     }
953 
954     override void visit(AST.DeclarationExp e)
955     {
956         //printf("Visiting DeclarationExp\n");
957         if (auto v = e.declaration.isVarDeclaration())
958             visitVarDecl(v);
959         else
960             e.declaration.accept(this);
961     }
962 
963     override void visit(AST.TypeidExp e)
964     {
965         //printf("Visiting TypeidExp\n");
966         visitObject(e.obj);
967     }
968 
969     override void visit(AST.TraitsExp e)
970     {
971         //printf("Visiting TraitExp\n");
972         if (e.args)
973             foreach (arg; *e.args)
974                 visitObject(arg);
975     }
976 
977     override void visit(AST.IsExp e)
978     {
979         //printf("Visiting IsExp\n");
980         visitType(e.targ);
981         if (e.tspec)
982             visitType(e.tspec);
983         if (e.parameters && e.parameters.dim)
984             visitTemplateParameters(e.parameters);
985     }
986 
987     override void visit(AST.UnaExp e)
988     {
989         //printf("Visiting UnaExp\n");
990         e.e1.accept(this);
991     }
992 
993     override void visit(AST.BinExp e)
994     {
995         //printf("Visiting BinExp\n");
996         e.e1.accept(this);
997         e.e2.accept(this);
998     }
999 
1000     override void visit(AST.CompileExp e)
1001     {
1002         //printf("Visiting CompileExp\n");
1003         visitArgs(e.exps);
1004     }
1005 
1006     override void visit(AST.ImportExp e)
1007     {
1008         //printf("Visiting ImportExp\n");
1009         e.e1.accept(this);
1010     }
1011 
1012     override void visit(AST.AssertExp e)
1013     {
1014         //printf("Visiting AssertExp\n");
1015         e.e1.accept(this);
1016         if (e.msg)
1017             e.msg.accept(this);
1018     }
1019 
1020     override void visit(AST.DotIdExp e)
1021     {
1022         //printf("Visiting DotIdExp\n");
1023         e.e1.accept(this);
1024     }
1025 
1026     override void visit(AST.DotTemplateInstanceExp e)
1027     {
1028         //printf("Visiting DotTemplateInstanceExp\n");
1029         e.e1.accept(this);
1030         e.ti.accept(this);
1031     }
1032 
1033     override void visit(AST.CallExp e)
1034     {
1035         //printf("Visiting CallExp\n");
1036         e.e1.accept(this);
1037         visitArgs(e.arguments);
1038     }
1039 
1040     override void visit(AST.PtrExp e)
1041     {
1042         //printf("Visiting PtrExp\n");
1043         e.e1.accept(this);
1044     }
1045 
1046     override void visit(AST.DeleteExp e)
1047     {
1048         //printf("Visiting DeleteExp\n");
1049         e.e1.accept(this);
1050     }
1051 
1052     override void visit(AST.CastExp e)
1053     {
1054         //printf("Visiting CastExp\n");
1055         if (e.to)
1056             visitType(e.to);
1057         e.e1.accept(this);
1058     }
1059 
1060     override void visit(AST.IntervalExp e)
1061     {
1062         //printf("Visiting IntervalExp\n");
1063         e.lwr.accept(this);
1064         e.upr.accept(this);
1065     }
1066 
1067     override void visit(AST.ArrayExp e)
1068     {
1069         //printf("Visiting ArrayExp\n");
1070         e.e1.accept(this);
1071         visitArgs(e.arguments);
1072     }
1073 
1074     override void visit(AST.PostExp e)
1075     {
1076         //printf("Visiting PostExp\n");
1077         e.e1.accept(this);
1078     }
1079 
1080     override void visit(AST.CondExp e)
1081     {
1082         //printf("Visiting CondExp\n");
1083         e.econd.accept(this);
1084         e.e1.accept(this);
1085         e.e2.accept(this);
1086     }
1087 
1088 // Template Parameter
1089 //===========================================================
1090 
1091     override void visit(AST.TemplateTypeParameter tp)
1092     {
1093         //printf("Visiting TemplateTypeParameter\n");
1094         if (tp.specType)
1095             visitType(tp.specType);
1096         if (tp.defaultType)
1097             visitType(tp.defaultType);
1098     }
1099 
1100     override void visit(AST.TemplateThisParameter tp)
1101     {
1102         //printf("Visiting TemplateThisParameter\n");
1103         visit(cast(AST.TemplateTypeParameter)tp);
1104     }
1105 
1106     override void visit(AST.TemplateAliasParameter tp)
1107     {
1108         //printf("Visiting TemplateAliasParameter\n");
1109         if (tp.specType)
1110             visitType(tp.specType);
1111         if (tp.specAlias)
1112             visitObject(tp.specAlias);
1113         if (tp.defaultAlias)
1114             visitObject(tp.defaultAlias);
1115     }
1116 
1117     override void visit(AST.TemplateValueParameter tp)
1118     {
1119         //printf("Visiting TemplateValueParameter\n");
1120         visitType(tp.valType);
1121         if (tp.specValue)
1122             tp.specValue.accept(this);
1123         if (tp.defaultValue)
1124             tp.defaultValue.accept(this);
1125     }
1126 
1127 //===========================================================
1128 
1129     override void visit(AST.StaticIfCondition c)
1130     {
1131         //printf("Visiting StaticIfCondition\n");
1132         c.exp.accept(this);
1133     }
1134 
1135     override void visit(AST.Parameter p)
1136     {
1137         //printf("Visiting Parameter\n");
1138         visitType(p.type);
1139         if (p.defaultArg)
1140             p.defaultArg.accept(this);
1141     }
1142 
1143     override void visit(AST.Module m)
1144     {
1145         //printf("Visiting Module\n");
1146         foreach (s; *m.members)
1147         {
1148            s.accept(this);
1149         }
1150     }
1151 }