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     override void visit(AST.TypeMixin t)
468     {
469         visitArgs(t.exps);
470     }
471 
472 //      Miscellaneous
473 //========================================================
474 
475     override void visit(AST.StaticAssert s)
476     {
477         //printf("Visiting StaticAssert\n");
478         s.exp.accept(this);
479         if (s.msg)
480             s.msg.accept(this);
481     }
482 
483     override void visit(AST.EnumMember em)
484     {
485         //printf("Visiting EnumMember\n");
486         if (em.type)
487             visitType(em.type);
488         if (em.value)
489             em.value.accept(this);
490     }
491 
492 //      Declarations
493 //=========================================================
494     void visitAttribDeclaration(AST.AttribDeclaration d)
495     {
496         if (d.decl)
497             foreach (de; *d.decl)
498                 de.accept(this);
499     }
500 
501     override void visit(AST.AttribDeclaration d)
502     {
503         //printf("Visiting AttribDeclaration\n");
504         visitAttribDeclaration(d);
505     }
506 
507     override void visit(AST.StorageClassDeclaration d)
508     {
509         //printf("Visiting StorageClassDeclaration\n");
510         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
511     }
512 
513     override void visit(AST.DeprecatedDeclaration d)
514     {
515         //printf("Visiting DeprecatedDeclaration\n");
516         d.msg.accept(this);
517         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
518     }
519 
520     override void visit(AST.LinkDeclaration d)
521     {
522         //printf("Visiting LinkDeclaration\n");
523         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
524     }
525 
526     override void visit(AST.CPPMangleDeclaration d)
527     {
528         //printf("Visiting CPPMangleDeclaration\n");
529         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
530     }
531 
532     override void visit(AST.VisibilityDeclaration d)
533     {
534         //printf("Visiting VisibilityDeclaration\n");
535         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
536     }
537 
538     override void visit(AST.AlignDeclaration d)
539     {
540         //printf("Visiting AlignDeclaration\n");
541         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
542     }
543 
544     override void visit(AST.AnonDeclaration d)
545     {
546         //printf("Visiting AnonDeclaration\n");
547         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
548     }
549 
550     override void visit(AST.PragmaDeclaration d)
551     {
552         //printf("Visiting PragmaDeclaration\n");
553         if (d.args && d.args.dim)
554             visitArgs(d.args);
555         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
556     }
557 
558     override void visit(AST.ConditionalDeclaration d)
559     {
560         //printf("Visiting ConditionalDeclaration\n");
561         d.condition.accept(this);
562         if (d.decl)
563             foreach (de; *d.decl)
564                 de.accept(this);
565         if (d.elsedecl)
566             foreach (de; *d.elsedecl)
567                 de.accept(this);
568     }
569 
570     override void visit(AST.CompileDeclaration d)
571     {
572         //printf("Visiting compileDeclaration\n");
573         visitArgs(d.exps);
574     }
575 
576     override void visit(AST.UserAttributeDeclaration d)
577     {
578         //printf("Visiting UserAttributeDeclaration\n");
579         visitArgs(d.atts);
580         visitAttribDeclaration(cast(AST.AttribDeclaration)d);
581     }
582 
583     void visitFuncBody(AST.FuncDeclaration f)
584     {
585         //printf("Visiting funcBody\n");
586         if (f.frequires)
587         {
588             foreach (frequire; *f.frequires)
589             {
590                 frequire.accept(this);
591             }
592         }
593         if (f.fensures)
594         {
595             foreach (fensure; *f.fensures)
596             {
597                 fensure.ensure.accept(this);
598             }
599         }
600         if (f.fbody)
601         {
602             f.fbody.accept(this);
603         }
604     }
605 
606     void visitBaseClasses(AST.ClassDeclaration d)
607     {
608         //printf("Visiting ClassDeclaration\n");
609         if (!d || !d.baseclasses.dim)
610             return;
611         foreach (b; *d.baseclasses)
612             visitType(b.type);
613     }
614 
615     bool visitEponymousMember(AST.TemplateDeclaration d)
616     {
617         //printf("Visiting EponymousMember\n");
618         if (!d.members || d.members.dim != 1)
619             return false;
620         AST.Dsymbol onemember = (*d.members)[0];
621         if (onemember.ident != d.ident)
622             return false;
623 
624         if (AST.FuncDeclaration fd = onemember.isFuncDeclaration())
625         {
626             assert(fd.type);
627             visitFunctionType(cast(AST.TypeFunction)fd.type, d);
628             if (d.constraint)
629                 d.constraint.accept(this);
630             visitFuncBody(fd);
631 
632             return true;
633         }
634 
635         if (AST.AggregateDeclaration ad = onemember.isAggregateDeclaration())
636         {
637             visitTemplateParameters(d.parameters);
638             if (d.constraint)
639                 d.constraint.accept(this);
640             visitBaseClasses(ad.isClassDeclaration());
641 
642             if (ad.members)
643                 foreach (s; *ad.members)
644                     s.accept(this);
645 
646             return true;
647         }
648 
649         if (AST.VarDeclaration vd = onemember.isVarDeclaration())
650         {
651             if (d.constraint)
652                 return false;
653             if (vd.type)
654                 visitType(vd.type);
655             visitTemplateParameters(d.parameters);
656             if (vd._init)
657             {
658                 AST.ExpInitializer ie = vd._init.isExpInitializer();
659                 if (ie && (ie.exp.op == TOK.construct || ie.exp.op == TOK.blit))
660                     (cast(AST.AssignExp)ie.exp).e2.accept(this);
661                 else
662                     vd._init.accept(this);
663 
664                 return true;
665             }
666         }
667 
668         return false;
669     }
670 
671     void visitTemplateParameters(AST.TemplateParameters* parameters)
672     {
673         if (!parameters || !parameters.dim)
674             return;
675         foreach (p; *parameters)
676             p.accept(this);
677     }
678 
679     override void visit(AST.TemplateDeclaration d)
680     {
681         //printf("Visiting TemplateDeclaration\n");
682         if (visitEponymousMember(d))
683             return;
684 
685         visitTemplateParameters(d.parameters);
686         if (d.constraint)
687             d.constraint.accept(this);
688 
689         foreach (s; *d.members)
690             s.accept(this);
691     }
692 
693     void visitObject(RootObject oarg)
694     {
695         if (auto t = AST.isType(oarg))
696         {
697             visitType(t);
698         }
699         else if (auto e = AST.isExpression(oarg))
700         {
701             e.accept(this);
702         }
703         else if (auto v = AST.isTuple(oarg))
704         {
705             auto args = &v.objects;
706             foreach (arg; *args)
707                 visitObject(arg);
708         }
709     }
710 
711     void visitTiargs(AST.TemplateInstance ti)
712     {
713         //printf("Visiting tiargs\n");
714         if (!ti.tiargs)
715             return;
716         foreach (arg; *ti.tiargs)
717         {
718             visitObject(arg);
719         }
720     }
721 
722     override void visit(AST.TemplateInstance ti)
723     {
724         //printf("Visiting TemplateInstance\n");
725         visitTiargs(ti);
726     }
727 
728     override void visit(AST.TemplateMixin tm)
729     {
730         //printf("Visiting TemplateMixin\n");
731         visitType(tm.tqual);
732         visitTiargs(tm);
733     }
734 
735     override void visit(AST.EnumDeclaration d)
736     {
737         //printf("Visiting EnumDeclaration\n");
738         if (d.memtype)
739             visitType(d.memtype);
740         if (!d.members)
741             return;
742         foreach (em; *d.members)
743         {
744             if (!em)
745                 continue;
746             em.accept(this);
747         }
748     }
749 
750     override void visit(AST.Nspace d)
751     {
752         //printf("Visiting Nspace\n");
753         foreach(s; *d.members)
754             s.accept(this);
755     }
756 
757     override void visit(AST.StructDeclaration d)
758     {
759         //printf("Visiting StructDeclaration\n");
760         if (!d.members)
761             return;
762         foreach (s; *d.members)
763             s.accept(this);
764     }
765 
766     override void visit(AST.ClassDeclaration d)
767     {
768         //printf("Visiting ClassDeclaration\n");
769         visitBaseClasses(d);
770         if (d.members)
771             foreach (s; *d.members)
772                 s.accept(this);
773     }
774 
775     override void visit(AST.AliasDeclaration d)
776     {
777         //printf("Visting AliasDeclaration\n");
778         if (d.aliassym)
779             d.aliassym.accept(this);
780         else
781             visitType(d.type);
782     }
783 
784     override void visit(AST.AliasAssign d)
785     {
786         //printf("Visting AliasAssign\n");
787         if (d.aliassym)
788             d.aliassym.accept(this);
789         else
790             visitType(d.type);
791     }
792 
793     override void visit(AST.VarDeclaration d)
794     {
795         //printf("Visiting VarDeclaration\n");
796         visitVarDecl(d);
797     }
798 
799     override void visit(AST.FuncDeclaration f)
800     {
801         //printf("Visiting FuncDeclaration\n");
802         auto tf = cast(AST.TypeFunction)f.type;
803         visitType(tf);
804         visitFuncBody(f);
805     }
806 
807     override void visit(AST.FuncLiteralDeclaration f)
808     {
809         //printf("Visiting FuncLiteralDeclaration\n");
810         if (f.type.ty == AST.Terror)
811             return;
812         AST.TypeFunction tf = cast(AST.TypeFunction)f.type;
813         if (!f.inferRetType && tf.next)
814             visitType(tf.next);
815         visitParameters(tf.parameterList.parameters);
816         AST.CompoundStatement cs = f.fbody.isCompoundStatement();
817         AST.Statement s = !cs ? f.fbody : null;
818         AST.ReturnStatement rs = s ? s.isReturnStatement() : null;
819         if (rs && rs.exp)
820             rs.exp.accept(this);
821         else
822             visitFuncBody(f);
823     }
824 
825     override void visit(AST.PostBlitDeclaration d)
826     {
827         //printf("Visiting PostBlitDeclaration\n");
828         visitFuncBody(d);
829     }
830 
831     override void visit(AST.DtorDeclaration d)
832     {
833         //printf("Visiting DtorDeclaration\n");
834         visitFuncBody(d);
835     }
836 
837     override void visit(AST.StaticCtorDeclaration d)
838     {
839         //printf("Visiting StaticCtorDeclaration\n");
840         visitFuncBody(d);
841     }
842 
843     override void visit(AST.StaticDtorDeclaration d)
844     {
845         //printf("Visiting StaticDtorDeclaration\n");
846         visitFuncBody(d);
847     }
848 
849     override void visit(AST.InvariantDeclaration d)
850     {
851         //printf("Visiting InvariantDeclaration\n");
852         visitFuncBody(d);
853     }
854 
855     override void visit(AST.UnitTestDeclaration d)
856     {
857         //printf("Visiting UnitTestDeclaration\n");
858         visitFuncBody(d);
859     }
860 
861     override void visit(AST.NewDeclaration d)
862     {
863         //printf("Visiting NewDeclaration\n");
864         visitParameters(d.parameterList.parameters);
865         visitFuncBody(d);
866     }
867 
868 //   Initializers
869 //============================================================
870 
871     override void visit(AST.StructInitializer si)
872     {
873         //printf("Visiting StructInitializer\n");
874         foreach (i, const id; si.field)
875             if (auto iz = si.value[i])
876                 iz.accept(this);
877     }
878 
879     override void visit(AST.ArrayInitializer ai)
880     {
881         //printf("Visiting ArrayInitializer\n");
882         foreach (i, ex; ai.index)
883         {
884             if (ex)
885                 ex.accept(this);
886             if (auto iz = ai.value[i])
887                 iz.accept(this);
888         }
889     }
890 
891     override void visit(AST.ExpInitializer ei)
892     {
893         //printf("Visiting ExpInitializer\n");
894         ei.exp.accept(this);
895     }
896 
897 //      Expressions
898 //===================================================
899 
900     override void visit(AST.ArrayLiteralExp e)
901     {
902         //printf("Visiting ArrayLiteralExp\n");
903         visitArgs(e.elements, e.basis);
904     }
905 
906     override void visit(AST.AssocArrayLiteralExp e)
907     {
908         //printf("Visiting AssocArrayLiteralExp\n");
909         foreach (i, key; *e.keys)
910         {
911             key.accept(this);
912             ((*e.values)[i]).accept(this);
913         }
914     }
915 
916     override void visit(AST.TypeExp e)
917     {
918         //printf("Visiting TypeExp\n");
919         visitType(e.type);
920     }
921 
922     override void visit(AST.ScopeExp e)
923     {
924         //printf("Visiting ScopeExp\n");
925         if (e.sds.isTemplateInstance())
926             e.sds.accept(this);
927     }
928 
929     override void visit(AST.NewExp e)
930     {
931         //printf("Visiting NewExp\n");
932         if (e.thisexp)
933             e.thisexp.accept(this);
934         if (e.newargs && e.newargs.dim)
935             visitArgs(e.newargs);
936         visitType(e.newtype);
937         if (e.arguments && e.arguments.dim)
938             visitArgs(e.arguments);
939     }
940 
941     override void visit(AST.NewAnonClassExp e)
942     {
943         //printf("Visiting NewAnonClassExp\n");
944         if (e.thisexp)
945             e.thisexp.accept(this);
946         if (e.newargs && e.newargs.dim)
947             visitArgs(e.newargs);
948         if (e.arguments && e.arguments.dim)
949             visitArgs(e.arguments);
950         if (e.cd)
951             e.cd.accept(this);
952     }
953 
954     override void visit(AST.TupleExp e)
955     {
956         //printf("Visiting TupleExp\n");
957         if (e.e0)
958             e.e0.accept(this);
959         visitArgs(e.exps);
960     }
961 
962     override void visit(AST.FuncExp e)
963     {
964         //printf("Visiting FuncExp\n");
965         e.fd.accept(this);
966     }
967 
968     override void visit(AST.DeclarationExp e)
969     {
970         //printf("Visiting DeclarationExp\n");
971         if (auto v = e.declaration.isVarDeclaration())
972             visitVarDecl(v);
973         else
974             e.declaration.accept(this);
975     }
976 
977     override void visit(AST.TypeidExp e)
978     {
979         //printf("Visiting TypeidExp\n");
980         visitObject(e.obj);
981     }
982 
983     override void visit(AST.TraitsExp e)
984     {
985         //printf("Visiting TraitExp\n");
986         if (e.args)
987             foreach (arg; *e.args)
988                 visitObject(arg);
989     }
990 
991     override void visit(AST.IsExp e)
992     {
993         //printf("Visiting IsExp\n");
994         visitType(e.targ);
995         if (e.tspec)
996             visitType(e.tspec);
997         if (e.parameters && e.parameters.dim)
998             visitTemplateParameters(e.parameters);
999     }
1000 
1001     override void visit(AST.UnaExp e)
1002     {
1003         //printf("Visiting UnaExp\n");
1004         e.e1.accept(this);
1005     }
1006 
1007     override void visit(AST.BinExp e)
1008     {
1009         //printf("Visiting BinExp\n");
1010         e.e1.accept(this);
1011         e.e2.accept(this);
1012     }
1013 
1014     override void visit(AST.MixinExp e)
1015     {
1016         //printf("Visiting MixinExp\n");
1017         visitArgs(e.exps);
1018     }
1019 
1020     override void visit(AST.ImportExp e)
1021     {
1022         //printf("Visiting ImportExp\n");
1023         e.e1.accept(this);
1024     }
1025 
1026     override void visit(AST.AssertExp e)
1027     {
1028         //printf("Visiting AssertExp\n");
1029         e.e1.accept(this);
1030         if (e.msg)
1031             e.msg.accept(this);
1032     }
1033 
1034     override void visit(AST.DotIdExp e)
1035     {
1036         //printf("Visiting DotIdExp\n");
1037         e.e1.accept(this);
1038     }
1039 
1040     override void visit(AST.DotTemplateInstanceExp e)
1041     {
1042         //printf("Visiting DotTemplateInstanceExp\n");
1043         e.e1.accept(this);
1044         e.ti.accept(this);
1045     }
1046 
1047     override void visit(AST.CallExp e)
1048     {
1049         //printf("Visiting CallExp\n");
1050         e.e1.accept(this);
1051         visitArgs(e.arguments);
1052     }
1053 
1054     override void visit(AST.PtrExp e)
1055     {
1056         //printf("Visiting PtrExp\n");
1057         e.e1.accept(this);
1058     }
1059 
1060     override void visit(AST.DeleteExp e)
1061     {
1062         //printf("Visiting DeleteExp\n");
1063         e.e1.accept(this);
1064     }
1065 
1066     override void visit(AST.CastExp e)
1067     {
1068         //printf("Visiting CastExp\n");
1069         if (e.to)
1070             visitType(e.to);
1071         e.e1.accept(this);
1072     }
1073 
1074     override void visit(AST.IntervalExp e)
1075     {
1076         //printf("Visiting IntervalExp\n");
1077         e.lwr.accept(this);
1078         e.upr.accept(this);
1079     }
1080 
1081     override void visit(AST.ArrayExp e)
1082     {
1083         //printf("Visiting ArrayExp\n");
1084         e.e1.accept(this);
1085         visitArgs(e.arguments);
1086     }
1087 
1088     override void visit(AST.PostExp e)
1089     {
1090         //printf("Visiting PostExp\n");
1091         e.e1.accept(this);
1092     }
1093 
1094     override void visit(AST.CondExp e)
1095     {
1096         //printf("Visiting CondExp\n");
1097         e.econd.accept(this);
1098         e.e1.accept(this);
1099         e.e2.accept(this);
1100     }
1101 
1102 // Template Parameter
1103 //===========================================================
1104 
1105     override void visit(AST.TemplateTypeParameter tp)
1106     {
1107         //printf("Visiting TemplateTypeParameter\n");
1108         if (tp.specType)
1109             visitType(tp.specType);
1110         if (tp.defaultType)
1111             visitType(tp.defaultType);
1112     }
1113 
1114     override void visit(AST.TemplateThisParameter tp)
1115     {
1116         //printf("Visiting TemplateThisParameter\n");
1117         visit(cast(AST.TemplateTypeParameter)tp);
1118     }
1119 
1120     override void visit(AST.TemplateAliasParameter tp)
1121     {
1122         //printf("Visiting TemplateAliasParameter\n");
1123         if (tp.specType)
1124             visitType(tp.specType);
1125         if (tp.specAlias)
1126             visitObject(tp.specAlias);
1127         if (tp.defaultAlias)
1128             visitObject(tp.defaultAlias);
1129     }
1130 
1131     override void visit(AST.TemplateValueParameter tp)
1132     {
1133         //printf("Visiting TemplateValueParameter\n");
1134         visitType(tp.valType);
1135         if (tp.specValue)
1136             tp.specValue.accept(this);
1137         if (tp.defaultValue)
1138             tp.defaultValue.accept(this);
1139     }
1140 
1141 //===========================================================
1142 
1143     override void visit(AST.StaticIfCondition c)
1144     {
1145         //printf("Visiting StaticIfCondition\n");
1146         c.exp.accept(this);
1147     }
1148 
1149     override void visit(AST.Parameter p)
1150     {
1151         //printf("Visiting Parameter\n");
1152         visitType(p.type);
1153         if (p.defaultArg)
1154             p.defaultArg.accept(this);
1155     }
1156 
1157     override void visit(AST.Module m)
1158     {
1159         //printf("Visiting Module\n");
1160         foreach (s; *m.members)
1161         {
1162            s.accept(this);
1163         }
1164     }
1165 }