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.ProtDeclaration d)
533     {
534         //printf("Visiting ProtDeclaration\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.VarDeclaration d)
785     {
786         //printf("Visiting VarDeclaration\n");
787         visitVarDecl(d);
788     }
789 
790     override void visit(AST.FuncDeclaration f)
791     {
792         //printf("Visiting FuncDeclaration\n");
793         auto tf = cast(AST.TypeFunction)f.type;
794         visitType(tf);
795         visitFuncBody(f);
796     }
797 
798     override void visit(AST.FuncLiteralDeclaration f)
799     {
800         //printf("Visiting FuncLiteralDeclaration\n");
801         if (f.type.ty == AST.Terror)
802             return;
803         AST.TypeFunction tf = cast(AST.TypeFunction)f.type;
804         if (!f.inferRetType && tf.next)
805             visitType(tf.next);
806         visitParameters(tf.parameterList.parameters);
807         AST.CompoundStatement cs = f.fbody.isCompoundStatement();
808         AST.Statement s = !cs ? f.fbody : null;
809         AST.ReturnStatement rs = s ? s.isReturnStatement() : null;
810         if (rs && rs.exp)
811             rs.exp.accept(this);
812         else
813             visitFuncBody(f);
814     }
815 
816     override void visit(AST.PostBlitDeclaration d)
817     {
818         //printf("Visiting PostBlitDeclaration\n");
819         visitFuncBody(d);
820     }
821 
822     override void visit(AST.DtorDeclaration d)
823     {
824         //printf("Visiting DtorDeclaration\n");
825         visitFuncBody(d);
826     }
827 
828     override void visit(AST.StaticCtorDeclaration d)
829     {
830         //printf("Visiting StaticCtorDeclaration\n");
831         visitFuncBody(d);
832     }
833 
834     override void visit(AST.StaticDtorDeclaration d)
835     {
836         //printf("Visiting StaticDtorDeclaration\n");
837         visitFuncBody(d);
838     }
839 
840     override void visit(AST.InvariantDeclaration d)
841     {
842         //printf("Visiting InvariantDeclaration\n");
843         visitFuncBody(d);
844     }
845 
846     override void visit(AST.UnitTestDeclaration d)
847     {
848         //printf("Visiting UnitTestDeclaration\n");
849         visitFuncBody(d);
850     }
851 
852     override void visit(AST.NewDeclaration d)
853     {
854         //printf("Visiting NewDeclaration\n");
855         visitParameters(d.parameterList.parameters);
856         visitFuncBody(d);
857     }
858 
859 //   Initializers
860 //============================================================
861 
862     override void visit(AST.StructInitializer si)
863     {
864         //printf("Visiting StructInitializer\n");
865         foreach (i, const id; si.field)
866             if (auto iz = si.value[i])
867                 iz.accept(this);
868     }
869 
870     override void visit(AST.ArrayInitializer ai)
871     {
872         //printf("Visiting ArrayInitializer\n");
873         foreach (i, ex; ai.index)
874         {
875             if (ex)
876                 ex.accept(this);
877             if (auto iz = ai.value[i])
878                 iz.accept(this);
879         }
880     }
881 
882     override void visit(AST.ExpInitializer ei)
883     {
884         //printf("Visiting ExpInitializer\n");
885         ei.exp.accept(this);
886     }
887 
888 //      Expressions
889 //===================================================
890 
891     override void visit(AST.ArrayLiteralExp e)
892     {
893         //printf("Visiting ArrayLiteralExp\n");
894         visitArgs(e.elements, e.basis);
895     }
896 
897     override void visit(AST.AssocArrayLiteralExp e)
898     {
899         //printf("Visiting AssocArrayLiteralExp\n");
900         foreach (i, key; *e.keys)
901         {
902             key.accept(this);
903             ((*e.values)[i]).accept(this);
904         }
905     }
906 
907     override void visit(AST.TypeExp e)
908     {
909         //printf("Visiting TypeExp\n");
910         visitType(e.type);
911     }
912 
913     override void visit(AST.ScopeExp e)
914     {
915         //printf("Visiting ScopeExp\n");
916         if (e.sds.isTemplateInstance())
917             e.sds.accept(this);
918     }
919 
920     override void visit(AST.NewExp e)
921     {
922         //printf("Visiting NewExp\n");
923         if (e.thisexp)
924             e.thisexp.accept(this);
925         if (e.newargs && e.newargs.dim)
926             visitArgs(e.newargs);
927         visitType(e.newtype);
928         if (e.arguments && e.arguments.dim)
929             visitArgs(e.arguments);
930     }
931 
932     override void visit(AST.NewAnonClassExp e)
933     {
934         //printf("Visiting NewAnonClassExp\n");
935         if (e.thisexp)
936             e.thisexp.accept(this);
937         if (e.newargs && e.newargs.dim)
938             visitArgs(e.newargs);
939         if (e.arguments && e.arguments.dim)
940             visitArgs(e.arguments);
941         if (e.cd)
942             e.cd.accept(this);
943     }
944 
945     override void visit(AST.TupleExp e)
946     {
947         //printf("Visiting TupleExp\n");
948         if (e.e0)
949             e.e0.accept(this);
950         visitArgs(e.exps);
951     }
952 
953     override void visit(AST.FuncExp e)
954     {
955         //printf("Visiting FuncExp\n");
956         e.fd.accept(this);
957     }
958 
959     override void visit(AST.DeclarationExp e)
960     {
961         //printf("Visiting DeclarationExp\n");
962         if (auto v = e.declaration.isVarDeclaration())
963             visitVarDecl(v);
964         else
965             e.declaration.accept(this);
966     }
967 
968     override void visit(AST.TypeidExp e)
969     {
970         //printf("Visiting TypeidExp\n");
971         visitObject(e.obj);
972     }
973 
974     override void visit(AST.TraitsExp e)
975     {
976         //printf("Visiting TraitExp\n");
977         if (e.args)
978             foreach (arg; *e.args)
979                 visitObject(arg);
980     }
981 
982     override void visit(AST.IsExp e)
983     {
984         //printf("Visiting IsExp\n");
985         visitType(e.targ);
986         if (e.tspec)
987             visitType(e.tspec);
988         if (e.parameters && e.parameters.dim)
989             visitTemplateParameters(e.parameters);
990     }
991 
992     override void visit(AST.UnaExp e)
993     {
994         //printf("Visiting UnaExp\n");
995         e.e1.accept(this);
996     }
997 
998     override void visit(AST.BinExp e)
999     {
1000         //printf("Visiting BinExp\n");
1001         e.e1.accept(this);
1002         e.e2.accept(this);
1003     }
1004 
1005     override void visit(AST.CompileExp e)
1006     {
1007         //printf("Visiting CompileExp\n");
1008         visitArgs(e.exps);
1009     }
1010 
1011     override void visit(AST.ImportExp e)
1012     {
1013         //printf("Visiting ImportExp\n");
1014         e.e1.accept(this);
1015     }
1016 
1017     override void visit(AST.AssertExp e)
1018     {
1019         //printf("Visiting AssertExp\n");
1020         e.e1.accept(this);
1021         if (e.msg)
1022             e.msg.accept(this);
1023     }
1024 
1025     override void visit(AST.DotIdExp e)
1026     {
1027         //printf("Visiting DotIdExp\n");
1028         e.e1.accept(this);
1029     }
1030 
1031     override void visit(AST.DotTemplateInstanceExp e)
1032     {
1033         //printf("Visiting DotTemplateInstanceExp\n");
1034         e.e1.accept(this);
1035         e.ti.accept(this);
1036     }
1037 
1038     override void visit(AST.CallExp e)
1039     {
1040         //printf("Visiting CallExp\n");
1041         e.e1.accept(this);
1042         visitArgs(e.arguments);
1043     }
1044 
1045     override void visit(AST.PtrExp e)
1046     {
1047         //printf("Visiting PtrExp\n");
1048         e.e1.accept(this);
1049     }
1050 
1051     override void visit(AST.DeleteExp e)
1052     {
1053         //printf("Visiting DeleteExp\n");
1054         e.e1.accept(this);
1055     }
1056 
1057     override void visit(AST.CastExp e)
1058     {
1059         //printf("Visiting CastExp\n");
1060         if (e.to)
1061             visitType(e.to);
1062         e.e1.accept(this);
1063     }
1064 
1065     override void visit(AST.IntervalExp e)
1066     {
1067         //printf("Visiting IntervalExp\n");
1068         e.lwr.accept(this);
1069         e.upr.accept(this);
1070     }
1071 
1072     override void visit(AST.ArrayExp e)
1073     {
1074         //printf("Visiting ArrayExp\n");
1075         e.e1.accept(this);
1076         visitArgs(e.arguments);
1077     }
1078 
1079     override void visit(AST.PostExp e)
1080     {
1081         //printf("Visiting PostExp\n");
1082         e.e1.accept(this);
1083     }
1084 
1085     override void visit(AST.CondExp e)
1086     {
1087         //printf("Visiting CondExp\n");
1088         e.econd.accept(this);
1089         e.e1.accept(this);
1090         e.e2.accept(this);
1091     }
1092 
1093 // Template Parameter
1094 //===========================================================
1095 
1096     override void visit(AST.TemplateTypeParameter tp)
1097     {
1098         //printf("Visiting TemplateTypeParameter\n");
1099         if (tp.specType)
1100             visitType(tp.specType);
1101         if (tp.defaultType)
1102             visitType(tp.defaultType);
1103     }
1104 
1105     override void visit(AST.TemplateThisParameter tp)
1106     {
1107         //printf("Visiting TemplateThisParameter\n");
1108         visit(cast(AST.TemplateTypeParameter)tp);
1109     }
1110 
1111     override void visit(AST.TemplateAliasParameter tp)
1112     {
1113         //printf("Visiting TemplateAliasParameter\n");
1114         if (tp.specType)
1115             visitType(tp.specType);
1116         if (tp.specAlias)
1117             visitObject(tp.specAlias);
1118         if (tp.defaultAlias)
1119             visitObject(tp.defaultAlias);
1120     }
1121 
1122     override void visit(AST.TemplateValueParameter tp)
1123     {
1124         //printf("Visiting TemplateValueParameter\n");
1125         visitType(tp.valType);
1126         if (tp.specValue)
1127             tp.specValue.accept(this);
1128         if (tp.defaultValue)
1129             tp.defaultValue.accept(this);
1130     }
1131 
1132 //===========================================================
1133 
1134     override void visit(AST.StaticIfCondition c)
1135     {
1136         //printf("Visiting StaticIfCondition\n");
1137         c.exp.accept(this);
1138     }
1139 
1140     override void visit(AST.Parameter p)
1141     {
1142         //printf("Visiting Parameter\n");
1143         visitType(p.type);
1144         if (p.defaultArg)
1145             p.defaultArg.accept(this);
1146     }
1147 
1148     override void visit(AST.Module m)
1149     {
1150         //printf("Visiting Module\n");
1151         foreach (s; *m.members)
1152         {
1153            s.accept(this);
1154         }
1155     }
1156 }