xref: /netbsd-src/external/gpl3/gcc/dist/gcc/d/dmd/init.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /**
2  * Defines initializers of variables, e.g. the array literal in `int[3] x = [0, 1, 2]`.
3  *
4  * Copyright:   Copyright (C) 1999-2022 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/init.d, _init.d)
8  * Documentation:  https://dlang.org/phobos/dmd_init.html
9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/init.d
10  */
11 
12 module dmd.init;
13 
14 import core.stdc.stdio;
15 import core.checkedint;
16 
17 import dmd.arraytypes;
18 import dmd.astenums;
19 import dmd.ast_node;
20 import dmd.dsymbol;
21 import dmd.expression;
22 import dmd.globals;
23 import dmd.hdrgen;
24 import dmd.identifier;
25 import dmd.mtype;
26 import dmd.common.outbuffer;
27 import dmd.root.rootobject;
28 import dmd.tokens;
29 import dmd.visitor;
30 
31 enum NeedInterpret : int
32 {
33     INITnointerpret,
34     INITinterpret,
35 }
36 
37 alias INITnointerpret = NeedInterpret.INITnointerpret;
38 alias INITinterpret = NeedInterpret.INITinterpret;
39 
40 /***********************************************************
41  */
42 extern (C++) class Initializer : ASTNode
43 {
44     Loc loc;
45     InitKind kind;
46 
dyncast()47     override DYNCAST dyncast() const nothrow pure
48     {
49         return DYNCAST.initializer;
50     }
51 
52 
this(const ref Loc loc,InitKind kind)53     extern (D) this(const ref Loc loc, InitKind kind)
54     {
55         this.loc = loc;
56         this.kind = kind;
57     }
58 
toChars()59     override final const(char)* toChars() const
60     {
61         OutBuffer buf;
62         HdrGenState hgs;
63         .toCBuffer(this, &buf, &hgs);
64         return buf.extractChars();
65     }
66 
inout(ErrorInitializer)67     final inout(ErrorInitializer) isErrorInitializer() inout @nogc nothrow pure
68     {
69         // Use void* cast to skip dynamic casting call
70         return kind == InitKind.error ? cast(inout ErrorInitializer)cast(void*)this : null;
71     }
72 
inout(VoidInitializer)73     final inout(VoidInitializer) isVoidInitializer() inout @nogc nothrow pure
74     {
75         return kind == InitKind.void_ ? cast(inout VoidInitializer)cast(void*)this : null;
76     }
77 
inout(StructInitializer)78     final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure
79     {
80         return kind == InitKind.struct_ ? cast(inout StructInitializer)cast(void*)this : null;
81     }
82 
inout(ArrayInitializer)83     final inout(ArrayInitializer) isArrayInitializer() inout @nogc nothrow pure
84     {
85         return kind == InitKind.array ? cast(inout ArrayInitializer)cast(void*)this : null;
86     }
87 
inout(ExpInitializer)88     final inout(ExpInitializer) isExpInitializer() inout @nogc nothrow pure
89     {
90         return kind == InitKind.exp ? cast(inout ExpInitializer)cast(void*)this : null;
91     }
92 
inout(CInitializer)93     final inout(CInitializer) isCInitializer() inout @nogc nothrow pure
94     {
95         return kind == InitKind.C_ ? cast(inout CInitializer)cast(void*)this : null;
96     }
97 
accept(Visitor v)98     override void accept(Visitor v)
99     {
100         v.visit(this);
101     }
102 }
103 
104 /***********************************************************
105  */
106 extern (C++) final class VoidInitializer : Initializer
107 {
108     Type type;      // type that this will initialize to
109 
this(const ref Loc loc)110     extern (D) this(const ref Loc loc)
111     {
112         super(loc, InitKind.void_);
113     }
114 
accept(Visitor v)115     override void accept(Visitor v)
116     {
117         v.visit(this);
118     }
119 }
120 
121 /***********************************************************
122  */
123 extern (C++) final class ErrorInitializer : Initializer
124 {
this()125     extern (D) this()
126     {
127         super(Loc.initial, InitKind.error);
128     }
129 
accept(Visitor v)130     override void accept(Visitor v)
131     {
132         v.visit(this);
133     }
134 }
135 
136 /***********************************************************
137  */
138 extern (C++) final class StructInitializer : Initializer
139 {
140     Identifiers field;      // of Identifier *'s
141     Initializers value;     // parallel array of Initializer *'s
142 
this(const ref Loc loc)143     extern (D) this(const ref Loc loc)
144     {
145         super(loc, InitKind.struct_);
146     }
147 
addInit(Identifier field,Initializer value)148     extern (D) void addInit(Identifier field, Initializer value)
149     {
150         //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
151         this.field.push(field);
152         this.value.push(value);
153     }
154 
accept(Visitor v)155     override void accept(Visitor v)
156     {
157         v.visit(this);
158     }
159 }
160 
161 /***********************************************************
162  */
163 extern (C++) final class ArrayInitializer : Initializer
164 {
165     Expressions index;      // indices
166     Initializers value;     // of Initializer *'s
167     uint dim;               // length of array being initialized
168     Type type;              // type that array will be used to initialize
169     bool sem;               // true if semantic() is run
170 
this(const ref Loc loc)171     extern (D) this(const ref Loc loc)
172     {
173         super(loc, InitKind.array);
174     }
175 
addInit(Expression index,Initializer value)176     extern (D) void addInit(Expression index, Initializer value)
177     {
178         this.index.push(index);
179         this.value.push(value);
180         dim = 0;
181         type = null;
182     }
183 
isAssociativeArray()184     bool isAssociativeArray() const pure
185     {
186         foreach (idx; index)
187         {
188             if (idx)
189                 return true;
190         }
191         return false;
192     }
193 
accept(Visitor v)194     override void accept(Visitor v)
195     {
196         v.visit(this);
197     }
198 }
199 
200 /***********************************************************
201  */
202 extern (C++) final class ExpInitializer : Initializer
203 {
204     bool expandTuples;
205     Expression exp;
206 
this(const ref Loc loc,Expression exp)207     extern (D) this(const ref Loc loc, Expression exp)
208     {
209         super(loc, InitKind.exp);
210         this.exp = exp;
211     }
212 
accept(Visitor v)213     override void accept(Visitor v)
214     {
215         v.visit(this);
216     }
217 }
218 
219 /*********************************************
220  * Holds the `designator` for C initializers
221  */
222 struct Designator
223 {
224     Expression exp;     /// [ constant-expression ]
225     Identifier ident;   /// . identifier
226 
thisDesignator227     this(Expression exp) { this.exp = exp; }
thisDesignator228     this(Identifier ident) { this.ident = ident; }
229 }
230 
231 /*********************************************
232  * Holds the `designation (opt) initializer` for C initializers
233  */
234 struct DesigInit
235 {
236     Designators* designatorList; /// designation (opt)
237     Initializer initializer;     /// initializer
238 }
239 
240 /********************************
241  * C11 6.7.9 Initialization
242  * Represents the C initializer-list
243  */
244 extern (C++) final class CInitializer : Initializer
245 {
246     DesigInits initializerList; /// initializer-list
247     Type type;              /// type that array will be used to initialize
248     bool sem;               /// true if semantic() is run
249 
this(const ref Loc loc)250     extern (D) this(const ref Loc loc)
251     {
252         super(loc, InitKind.C_);
253     }
254 
accept(Visitor v)255     override void accept(Visitor v)
256     {
257         v.visit(this);
258     }
259 }
260 
261 /****************************************
262  * Copy the AST for Initializer.
263  * Params:
264  *      inx = Initializer AST to copy
265  * Returns:
266  *      the copy
267  */
syntaxCopy(Initializer inx)268 Initializer syntaxCopy(Initializer inx)
269 {
270     static Initializer copyStruct(StructInitializer vi)
271     {
272         auto si = new StructInitializer(vi.loc);
273         assert(vi.field.dim == vi.value.dim);
274         si.field.setDim(vi.field.dim);
275         si.value.setDim(vi.value.dim);
276         foreach (const i; 0 .. vi.field.dim)
277         {
278             si.field[i] = vi.field[i];
279             si.value[i] = vi.value[i].syntaxCopy();
280         }
281         return si;
282     }
283 
284     static Initializer copyArray(ArrayInitializer vi)
285     {
286         auto ai = new ArrayInitializer(vi.loc);
287         assert(vi.index.dim == vi.value.dim);
288         ai.index.setDim(vi.index.dim);
289         ai.value.setDim(vi.value.dim);
290         foreach (const i; 0 .. vi.value.dim)
291         {
292             ai.index[i] = vi.index[i] ? vi.index[i].syntaxCopy() : null;
293             ai.value[i] = vi.value[i].syntaxCopy();
294         }
295         return ai;
296     }
297 
298     static Initializer copyC(CInitializer vi)
299     {
300         auto ci = new CInitializer(vi.loc);
301         ci.initializerList.setDim(vi.initializerList.length);
302         foreach (const i; 0 .. vi.initializerList.length)
303         {
304             DesigInit* cdi = &ci.initializerList[i];
305             DesigInit* vdi = &ci.initializerList[i];
306             cdi.initializer = vdi.initializer.syntaxCopy();
307             if (vdi.designatorList)
308             {
309                 cdi.designatorList = new Designators();
310                 cdi.designatorList.setDim(vdi.designatorList.length);
311                 foreach (const j; 0 .. vdi.designatorList.length)
312                 {
313                     Designator* cdid = &(*cdi.designatorList)[j];
314                     Designator* vdid = &(*vdi.designatorList)[j];
315                     cdid.exp = vdid.exp ? vdid.exp.syntaxCopy() : null;
316                     cdid.ident = vdid.ident;
317                 }
318             }
319         }
320         return ci;
321     }
322 
323     final switch (inx.kind)
324     {
325         case InitKind.void_:   return new VoidInitializer(inx.loc);
326         case InitKind.error:   return inx;
327         case InitKind.struct_: return copyStruct(cast(StructInitializer)inx);
328         case InitKind.array:   return copyArray(cast(ArrayInitializer)inx);
329         case InitKind.exp:     return new ExpInitializer(inx.loc, (cast(ExpInitializer)inx).exp.syntaxCopy());
330         case InitKind.C_:      return copyC(cast(CInitializer)inx);
331     }
332 }
333