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