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