d: Merge upstream dmd ff57fec515, druntime ff57fec515, phobos 17bafda79.
[official-gcc.git] / gcc / d / dmd / init.d
blobe48410082bdb256259680ee57299db049697d1c2
1 /**
2 * Defines initializers of variables, e.g. the array literal in `int[3] x = [0, 1, 2]`.
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/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
12 module dmd.init;
14 import core.stdc.stdio;
15 import core.checkedint;
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.location;
26 import dmd.mtype;
27 import dmd.common.outbuffer;
28 import dmd.rootobject;
29 import dmd.tokens;
30 import dmd.visitor;
32 enum NeedInterpret : int
34 INITnointerpret,
35 INITinterpret,
38 alias INITnointerpret = NeedInterpret.INITnointerpret;
39 alias INITinterpret = NeedInterpret.INITinterpret;
41 /***********************************************************
43 extern (C++) class Initializer : ASTNode
45 Loc loc;
46 InitKind kind;
48 override DYNCAST dyncast() const
50 return DYNCAST.initializer;
54 extern (D) this(const ref Loc loc, InitKind kind) @safe
56 this.loc = loc;
57 this.kind = kind;
60 final inout(ErrorInitializer) isErrorInitializer() inout @nogc nothrow pure
62 // Use void* cast to skip dynamic casting call
63 return kind == InitKind.error ? cast(inout ErrorInitializer)cast(void*)this : null;
66 final inout(VoidInitializer) isVoidInitializer() inout @nogc nothrow pure
68 return kind == InitKind.void_ ? cast(inout VoidInitializer)cast(void*)this : null;
71 final inout(DefaultInitializer) isDefaultInitializer() inout @nogc nothrow pure
73 return kind == InitKind.default_ ? cast(inout DefaultInitializer)cast(void*)this : null;
76 final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure
78 return kind == InitKind.struct_ ? cast(inout StructInitializer)cast(void*)this : null;
81 final inout(ArrayInitializer) isArrayInitializer() inout @nogc nothrow pure
83 return kind == InitKind.array ? cast(inout ArrayInitializer)cast(void*)this : null;
86 final inout(ExpInitializer) isExpInitializer() inout @nogc nothrow pure
88 return kind == InitKind.exp ? cast(inout ExpInitializer)cast(void*)this : null;
91 final inout(CInitializer) isCInitializer() inout @nogc nothrow pure
93 return kind == InitKind.C_ ? cast(inout CInitializer)cast(void*)this : null;
96 override void accept(Visitor v)
98 v.visit(this);
102 /***********************************************************
104 extern (C++) final class VoidInitializer : Initializer
106 Type type; // type that this will initialize to
108 extern (D) this(const ref Loc loc) @safe
110 super(loc, InitKind.void_);
113 override void accept(Visitor v)
115 v.visit(this);
119 /***********************************************************
120 * The C23 default initializer `{ }`
122 extern (C++) final class DefaultInitializer : Initializer
124 Type type; // type that this will initialize to
126 extern (D) this(const ref Loc loc) @safe
128 super(loc, InitKind.default_);
131 override void accept(Visitor v)
133 v.visit(this);
137 /***********************************************************
139 extern (C++) final class ErrorInitializer : Initializer
141 extern (D) this() @safe
143 super(Loc.initial, InitKind.error);
146 override void accept(Visitor v)
148 v.visit(this);
152 /***********************************************************
154 extern (C++) final class StructInitializer : Initializer
156 Identifiers field; // of Identifier *'s
157 Initializers value; // parallel array of Initializer *'s
159 extern (D) this(const ref Loc loc)
161 super(loc, InitKind.struct_);
164 extern (D) void addInit(Identifier field, Initializer value)
166 //printf("StructInitializer::addInit(field = %p, value = %p)\n", field, value);
167 this.field.push(field);
168 this.value.push(value);
171 override void accept(Visitor v)
173 v.visit(this);
177 /***********************************************************
179 extern (C++) final class ArrayInitializer : Initializer
181 Expressions index; // indices
182 Initializers value; // of Initializer *'s
183 uint dim; // length of array being initialized
184 Type type; // type that array will be used to initialize
185 bool sem; // true if semantic() is run
186 bool isCarray; // C array semantics
188 extern (D) this(const ref Loc loc)
190 super(loc, InitKind.array);
193 extern (D) void addInit(Expression index, Initializer value)
195 this.index.push(index);
196 this.value.push(value);
197 dim = 0;
198 type = null;
201 bool isAssociativeArray() const pure
203 foreach (idx; index)
205 if (idx)
206 return true;
208 return false;
211 override void accept(Visitor v)
213 v.visit(this);
217 /***********************************************************
219 extern (C++) final class ExpInitializer : Initializer
221 bool expandTuples;
222 Expression exp;
224 extern (D) this(const ref Loc loc, Expression exp) @safe
226 super(loc, InitKind.exp);
227 this.exp = exp;
230 override void accept(Visitor v)
232 v.visit(this);
236 /*********************************************
237 * Holds the `designator` for C initializers
239 struct Designator
241 Expression exp; /// [ constant-expression ]
242 Identifier ident; /// . identifier
244 this(Expression exp) @safe { this.exp = exp; }
245 this(Identifier ident) @safe { this.ident = ident; }
248 /*********************************************
249 * Holds the `designation (opt) initializer` for C initializers
251 struct DesigInit
253 Designators* designatorList; /// designation (opt)
254 Initializer initializer; /// initializer
257 /********************************
258 * C11 6.7.9 Initialization
259 * Represents the C initializer-list
261 extern (C++) final class CInitializer : Initializer
263 DesigInits initializerList; /// initializer-list
264 Type type; /// type that array will be used to initialize
265 bool sem; /// true if semantic() is run
267 extern (D) this(const ref Loc loc)
269 super(loc, InitKind.C_);
272 override void accept(Visitor v)
274 v.visit(this);
278 /****************************************
279 * Copy the AST for Initializer.
280 * Params:
281 * inx = Initializer AST to copy
282 * Returns:
283 * the copy
285 Initializer syntaxCopy(Initializer inx)
287 static Initializer visitVoid(VoidInitializer vi)
289 return new VoidInitializer(vi.loc);
292 static Initializer visitDefault(DefaultInitializer vi)
294 return new DefaultInitializer(vi.loc);
297 static Initializer visitError(ErrorInitializer vi)
299 return vi;
302 static Initializer visitExp(ExpInitializer vi)
304 return new ExpInitializer(vi.loc, vi.exp.syntaxCopy());
307 static Initializer visitStruct(StructInitializer vi)
309 auto si = new StructInitializer(vi.loc);
310 assert(vi.field.length == vi.value.length);
311 si.field.setDim(vi.field.length);
312 si.value.setDim(vi.value.length);
313 foreach (const i; 0 .. vi.field.length)
315 si.field[i] = vi.field[i];
316 si.value[i] = vi.value[i].syntaxCopy();
318 return si;
321 static Initializer visitArray(ArrayInitializer vi)
323 auto ai = new ArrayInitializer(vi.loc);
324 assert(vi.index.length == vi.value.length);
325 ai.index.setDim(vi.index.length);
326 ai.value.setDim(vi.value.length);
327 foreach (const i; 0 .. vi.value.length)
329 ai.index[i] = vi.index[i] ? vi.index[i].syntaxCopy() : null;
330 ai.value[i] = vi.value[i].syntaxCopy();
332 return ai;
335 static Initializer visitC(CInitializer vi)
337 auto ci = new CInitializer(vi.loc);
338 ci.initializerList.setDim(vi.initializerList.length);
339 foreach (const i; 0 .. vi.initializerList.length)
341 DesigInit* cdi = &ci.initializerList[i];
342 DesigInit* vdi = &ci.initializerList[i];
343 cdi.initializer = vdi.initializer.syntaxCopy();
344 if (vdi.designatorList)
346 cdi.designatorList = new Designators();
347 cdi.designatorList.setDim(vdi.designatorList.length);
348 foreach (const j; 0 .. vdi.designatorList.length)
350 Designator* cdid = &(*cdi.designatorList)[j];
351 Designator* vdid = &(*vdi.designatorList)[j];
352 cdid.exp = vdid.exp ? vdid.exp.syntaxCopy() : null;
353 cdid.ident = vdid.ident;
357 return ci;
360 mixin VisitInitializer!Initializer visit;
361 return visit.VisitInitializer(inx);
364 /***********************************************************
365 * Visit each Initializer in init. Call a function visit%s(init) for
366 * each node, where %s is the op of the node. Otherwise call visitDefault(init)
367 * for that node. If the visit function returns R.init, continue
368 * visiting each node, otherwise return the value of R.
369 * Params:
370 * Result = return type
371 * init = Initializer tree to traverse
372 * Returns:
373 * Result.init for continue, value of type Result for early exit
376 mixin template VisitInitializer(Result)
378 Result VisitInitializer(Initializer init)
380 final switch (init.kind)
382 case InitKind.void_: mixin(visitCase("Void")); break;
383 case InitKind.default_: mixin(visitCase("Default")); break;
384 case InitKind.error: mixin(visitCase("Error")); break;
385 case InitKind.struct_: mixin(visitCase("Struct")); break;
386 case InitKind.array: mixin(visitCase("Array")); break;
387 case InitKind.exp: mixin(visitCase("Exp")); break;
388 case InitKind.C_: mixin(visitCase("C")); break;
390 static if (is(Result == void)) { } else
391 return Result.init;
395 /****************************************
396 * CTFE-only helper function for VisitInitializer.
397 * Params:
398 * handler = string for the name of the visit handler
399 * Returns: boilerplate code for a case
401 string visitCase(string handler) pure @safe
403 if (__ctfe)
405 return
407 auto ix = init.is"~handler~"Initializer();
408 static if (is(Result == void))
409 visit"~handler~"(ix);
410 else
412 Result r = visit"~handler~"(ix);
413 if (r !is Result.init)
414 return r;
418 assert(0);