1 /**
2  * Provides a visitor class visiting all AST nodes present in the compiler.
3  *
4  * Copyright:   Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved
5  * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
6  * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/visitor.d, _visitor.d)
8  * Documentation:  https://dlang.org/phobos/dmd_visitor.html
9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/visitor.d
10  */
11 
12 module dmd.visitor;
13 
14 import dmd.astcodegen;
15 import dmd.astenums;
16 import dmd.parsetimevisitor;
17 import dmd.tokens;
18 import dmd.transitivevisitor;
19 import dmd.expression;
20 import dmd.rootobject;
21 
22 /**
23  * Classic Visitor class which implements visit methods for all the AST
24  * nodes present in the compiler. The visit methods for AST nodes
25  * created at parse time are inherited while the visiting methods
26  * for AST nodes created at semantic time are implemented.
27  */
28 extern (C++) class Visitor : ParseTimeVisitor!ASTCodegen
29 {
30     alias visit = ParseTimeVisitor!ASTCodegen.visit;
31 public:
32     void visit(ASTCodegen.ErrorStatement s) { visit(cast(ASTCodegen.Statement)s); }
33     void visit(ASTCodegen.PeelStatement s) { visit(cast(ASTCodegen.Statement)s); }
34     void visit(ASTCodegen.UnrolledLoopStatement s) { visit(cast(ASTCodegen.Statement)s); }
35     void visit(ASTCodegen.SwitchErrorStatement s) { visit(cast(ASTCodegen.Statement)s); }
36     void visit(ASTCodegen.DebugStatement s) { visit(cast(ASTCodegen.Statement)s); }
37     void visit(ASTCodegen.DtorExpStatement s) { visit(cast(ASTCodegen.ExpStatement)s); }
38     void visit(ASTCodegen.ForwardingStatement s) { visit(cast(ASTCodegen.Statement)s); }
39     void visit(ASTCodegen.OverloadSet s) { visit(cast(ASTCodegen.Dsymbol)s); }
40     void visit(ASTCodegen.LabelDsymbol s) { visit(cast(ASTCodegen.Dsymbol)s); }
41     void visit(ASTCodegen.WithScopeSymbol s) { visit(cast(ASTCodegen.ScopeDsymbol)s); }
42     void visit(ASTCodegen.ArrayScopeSymbol s) { visit(cast(ASTCodegen.ScopeDsymbol)s); }
43     void visit(ASTCodegen.OverDeclaration s) { visit(cast(ASTCodegen.Declaration)s); }
44     void visit(ASTCodegen.SymbolDeclaration s) { visit(cast(ASTCodegen.Declaration)s); }
45     void visit(ASTCodegen.ForwardingAttribDeclaration s) { visit(cast(ASTCodegen.AttribDeclaration)s); }
46     void visit(ASTCodegen.ThisDeclaration s) { visit(cast(ASTCodegen.VarDeclaration)s); }
47     void visit(ASTCodegen.TypeInfoDeclaration s) { visit(cast(ASTCodegen.VarDeclaration)s); }
48     void visit(ASTCodegen.TypeInfoStructDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
49     void visit(ASTCodegen.TypeInfoClassDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
50     void visit(ASTCodegen.TypeInfoInterfaceDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
51     void visit(ASTCodegen.TypeInfoPointerDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
52     void visit(ASTCodegen.TypeInfoArrayDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
53     void visit(ASTCodegen.TypeInfoStaticArrayDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
54     void visit(ASTCodegen.TypeInfoAssociativeArrayDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
55     void visit(ASTCodegen.TypeInfoEnumDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
56     void visit(ASTCodegen.TypeInfoFunctionDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
57     void visit(ASTCodegen.TypeInfoDelegateDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
58     void visit(ASTCodegen.TypeInfoTupleDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
59     void visit(ASTCodegen.TypeInfoConstDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
60     void visit(ASTCodegen.TypeInfoInvariantDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
61     void visit(ASTCodegen.TypeInfoSharedDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
62     void visit(ASTCodegen.TypeInfoWildDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
63     void visit(ASTCodegen.TypeInfoVectorDeclaration s) { visit(cast(ASTCodegen.TypeInfoDeclaration)s); }
64     void visit(ASTCodegen.FuncAliasDeclaration s) { visit(cast(ASTCodegen.FuncDeclaration)s); }
65     void visit(ASTCodegen.ErrorInitializer i) { visit(cast(ASTCodegen.Initializer)i); }
66     void visit(ASTCodegen.ErrorExp e) { visit(cast(ASTCodegen.Expression)e); }
67     void visit(ASTCodegen.ComplexExp e) { visit(cast(ASTCodegen.Expression)e); }
68     void visit(ASTCodegen.StructLiteralExp e) { visit(cast(ASTCodegen.Expression)e); }
69     void visit(ASTCodegen.CompoundLiteralExp e) { visit(cast(ASTCodegen.Expression)e); }
70     void visit(ASTCodegen.ObjcClassReferenceExp e) { visit(cast(ASTCodegen.Expression)e); }
71     void visit(ASTCodegen.SymOffExp e) { visit(cast(ASTCodegen.SymbolExp)e); }
72     void visit(ASTCodegen.OverExp e) { visit(cast(ASTCodegen.Expression)e); }
73     void visit(ASTCodegen.HaltExp e) { visit(cast(ASTCodegen.Expression)e); }
74     void visit(ASTCodegen.DotTemplateExp e) { visit(cast(ASTCodegen.UnaExp)e); }
75     void visit(ASTCodegen.DotVarExp e) { visit(cast(ASTCodegen.UnaExp)e); }
76     void visit(ASTCodegen.DelegateExp e) { visit(cast(ASTCodegen.UnaExp)e); }
77     void visit(ASTCodegen.DotTypeExp e) { visit(cast(ASTCodegen.UnaExp)e); }
78     void visit(ASTCodegen.VectorExp e) { visit(cast(ASTCodegen.UnaExp)e); }
79     void visit(ASTCodegen.VectorArrayExp e) { visit(cast(ASTCodegen.UnaExp)e); }
80     void visit(ASTCodegen.SliceExp e) { visit(cast(ASTCodegen.UnaExp)e); }
81     void visit(ASTCodegen.ArrayLengthExp e) { visit(cast(ASTCodegen.UnaExp)e); }
82     void visit(ASTCodegen.DelegatePtrExp e) { visit(cast(ASTCodegen.UnaExp)e); }
83     void visit(ASTCodegen.DelegateFuncptrExp e) { visit(cast(ASTCodegen.UnaExp)e); }
84     void visit(ASTCodegen.DotExp e) { visit(cast(ASTCodegen.BinExp)e); }
85     void visit(ASTCodegen.IndexExp e) { visit(cast(ASTCodegen.BinExp)e); }
86     void visit(ASTCodegen.ConstructExp e) { visit(cast(ASTCodegen.AssignExp)e); }
87     void visit(ASTCodegen.BlitExp e) { visit(cast(ASTCodegen.AssignExp)e); }
88     void visit(ASTCodegen.RemoveExp e) { visit(cast(ASTCodegen.BinExp)e); }
89     void visit(ASTCodegen.ClassReferenceExp e) { visit(cast(ASTCodegen.Expression)e); }
90     void visit(ASTCodegen.VoidInitExp e) { visit(cast(ASTCodegen.Expression)e); }
91     void visit(ASTCodegen.ThrownExceptionExp e) { visit(cast(ASTCodegen.Expression)e); }
92     void visit(ASTCodegen.LoweredAssignExp e) { visit(cast(ASTCodegen.AssignExp)e); }
93 }
94 
95 /**
96  * The PermissiveVisitor overrides the root AST nodes with
97  * empty visiting methods.
98  */
99 extern (C++) class SemanticTimePermissiveVisitor : Visitor
100 {
101     alias visit = Visitor.visit;
102 
103     override void visit(ASTCodegen.Dsymbol){}
104     override void visit(ASTCodegen.Parameter){}
105     override void visit(ASTCodegen.Statement){}
106     override void visit(ASTCodegen.Type){}
107     override void visit(ASTCodegen.Expression){}
108     override void visit(ASTCodegen.TemplateParameter){}
109     override void visit(ASTCodegen.Condition){}
110     override void visit(ASTCodegen.Initializer){}
111 }
112 
113 /**
114  * The TransitiveVisitor implements the AST traversal logic for all AST nodes.
115  */
116 extern (C++) class SemanticTimeTransitiveVisitor : SemanticTimePermissiveVisitor
117 {
118     alias visit = SemanticTimePermissiveVisitor.visit;
119 
120     mixin ParseVisitMethods!ASTCodegen __methods;
121     alias visit = __methods.visit;
122 
123     override void visit(ASTCodegen.PeelStatement s)
124     {
125         if (s.s)
126             s.s.accept(this);
127     }
128 
129     override void visit(ASTCodegen.UnrolledLoopStatement s)
130     {
131         foreach(sx; *s.statements)
132         {
133             if (sx)
134                 sx.accept(this);
135         }
136     }
137 
138     override void visit(ASTCodegen.DebugStatement s)
139     {
140         if (s.statement)
141             s.statement.accept(this);
142     }
143 
144     override void visit(ASTCodegen.ForwardingStatement s)
145     {
146         if (s.statement)
147             s.statement.accept(this);
148     }
149 
150     override void visit(ASTCodegen.StructLiteralExp e)
151     {
152         // CTFE can generate struct literals that contain an AddrExp pointing to themselves,
153         // need to avoid infinite recursion.
154         if (!(e.stageflags & stageToCBuffer))
155         {
156             const old = e.stageflags;
157             e.stageflags |= stageToCBuffer;
158             foreach (el; *e.elements)
159                 if (el)
160                     el.accept(this);
161             e.stageflags = old;
162         }
163     }
164 
165     override void visit(ASTCodegen.CompoundLiteralExp e)
166     {
167         if (e.initializer)
168             e.initializer.accept(this);
169     }
170 
171     override void visit(ASTCodegen.DotTemplateExp e)
172     {
173         e.e1.accept(this);
174     }
175 
176     override void visit(ASTCodegen.DotVarExp e)
177     {
178         e.e1.accept(this);
179     }
180 
181     override void visit(ASTCodegen.DelegateExp e)
182     {
183         if (!e.func.isNested() || e.func.needThis())
184             e.e1.accept(this);
185     }
186 
187     override void visit(ASTCodegen.DotTypeExp e)
188     {
189         e.e1.accept(this);
190     }
191 
192     override void visit(ASTCodegen.VectorExp e)
193     {
194         visitType(e.to);
195         e.e1.accept(this);
196     }
197 
198     override void visit(ASTCodegen.VectorArrayExp e)
199     {
200         e.e1.accept(this);
201     }
202 
203     override void visit(ASTCodegen.SliceExp e)
204     {
205         e.e1.accept(this);
206         if (e.upr)
207             e.upr.accept(this);
208         if (e.lwr)
209             e.lwr.accept(this);
210     }
211 
212     override void visit(ASTCodegen.ArrayLengthExp e)
213     {
214         e.e1.accept(this);
215     }
216 
217     override void visit(ASTCodegen.DelegatePtrExp e)
218     {
219         e.e1.accept(this);
220     }
221 
222     override void visit(ASTCodegen.DelegateFuncptrExp e)
223     {
224         e.e1.accept(this);
225     }
226 
227     override void visit(ASTCodegen.DotExp e)
228     {
229         e.e1.accept(this);
230         e.e2.accept(this);
231     }
232 
233     override void visit(ASTCodegen.IndexExp e)
234     {
235         e.e1.accept(this);
236         e.e2.accept(this);
237     }
238 
239     override void visit(ASTCodegen.RemoveExp e)
240     {
241         e.e1.accept(this);
242         e.e2.accept(this);
243     }
244 
245     override void visit(ASTCodegen.LoweredAssignExp e)
246     {
247         e.lowering.accept(this);
248         visit(cast(AssignExp)e);
249     }
250 }
251 
252 extern (C++) class StoppableVisitor : Visitor
253 {
254     alias visit = Visitor.visit;
255 public:
256     bool stop;
257 
258     final extern (D) this() scope @safe
259     {
260     }
261 }