d: Merge upstream dmd, druntime 4c18eed967, phobos d945686a4.
[official-gcc.git] / gcc / d / dmd / initsem.d
blob28c7c2bb52e9298333011e546256f1fddf545ea5
1 /**
2 * Semantic analysis of initializers.
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/initsem.d, _initsem.d)
8 * Documentation: https://dlang.org/phobos/dmd_initsem.html
9 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/initsem.d
12 module dmd.initsem;
14 import core.stdc.stdio;
15 import core.checkedint;
17 import dmd.aggregate;
18 import dmd.aliasthis;
19 import dmd.arraytypes;
20 import dmd.astenums;
21 import dmd.dcast;
22 import dmd.declaration;
23 import dmd.dscope;
24 import dmd.dstruct;
25 import dmd.dsymbol;
26 import dmd.dtemplate;
27 import dmd.errors;
28 import dmd.expression;
29 import dmd.expressionsem;
30 import dmd.func;
31 import dmd.globals;
32 import dmd.hdrgen;
33 import dmd.id;
34 import dmd.identifier;
35 import dmd.importc;
36 import dmd.init;
37 import dmd.location;
38 import dmd.mtype;
39 import dmd.opover;
40 import dmd.statement;
41 import dmd.target;
42 import dmd.tokens;
43 import dmd.typesem;
45 /********************************
46 * If possible, convert array initializer to associative array initializer.
48 * Params:
49 * ai = array initializer to be converted
51 * Returns:
52 * The converted associative array initializer or ErrorExp if `ai`
53 * is not an associative array initializer.
55 Expression toAssocArrayLiteral(ArrayInitializer ai)
57 //printf("ArrayInitializer::toAssocArrayInitializer(%s)\n", ai.toChars());
58 //static int i; if (++i == 2) assert(0);
59 const dim = ai.value.length;
60 if (!dim)
62 error(ai.loc, "invalid associative array initializer `%s`, use `null` instead",
63 toChars(ai));
64 return ErrorExp.get();
66 auto no(const char* format, Initializer i)
68 error(i.loc, format, toChars(i));
69 return ErrorExp.get();
71 Expression e;
72 auto keys = new Expressions(dim);
73 auto values = new Expressions(dim);
74 for (size_t i = 0; i < dim; i++)
76 Initializer iz = ai.value[i];
77 assert(iz);
78 e = iz.initializerToExpression();
79 if (!e)
80 return no("invalid value `%s` in initializer", iz);
81 (*values)[i] = e;
82 e = ai.index[i];
83 if (!e)
84 return no("missing key for value `%s` in initializer", iz);
85 (*keys)[i] = e;
87 e = new AssocArrayLiteralExp(ai.loc, keys, values);
88 return e;
91 /******************************************
92 * Perform semantic analysis on init.
93 * Params:
94 * init = Initializer AST node
95 * sc = context
96 * tx = type that the initializer needs to become. If tx is an incomplete
97 * type and the initializer completes it, it is updated to be the
98 * complete type. ImportC has incomplete types
99 * needInterpret = if CTFE needs to be run on this,
100 * such as if it is the initializer for a const declaration
101 * Returns:
102 * `Initializer` with completed semantic analysis, `ErrorInitializer` if errors
103 * were encountered
105 extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
107 Type t = tx;
109 static Initializer err()
111 return new ErrorInitializer();
114 Initializer visitVoid(VoidInitializer i)
116 i.type = t;
117 return i;
120 Initializer visitError(ErrorInitializer i)
122 return i;
125 Initializer visitStruct(StructInitializer i)
127 //printf("StructInitializer::semantic(t = %s) %s\n", t.toChars(), i.toChars());
128 /* This works by replacing the StructInitializer with an ExpInitializer.
130 t = t.toBasetype();
131 if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct)
132 t = t.nextOf().toBasetype();
133 if (auto ts = t.isTypeStruct())
135 StructDeclaration sd = ts.sym;
136 // check if the sd has a regular ctor (user defined non-copy ctor)
137 // that is not disabled.
138 if (sd.hasRegularCtor(true))
140 error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars());
141 return err();
143 sd.size(i.loc);
144 if (sd.sizeok != Sizeok.done)
145 return err();
147 Expression getExp(size_t j, Type fieldType)
149 // Convert initializer to Expression `ex`
150 auto tm = fieldType.addMod(t.mod);
151 auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret);
152 auto ex = iz.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
153 if (ex.op != EXP.error)
154 i.value[j] = iz;
155 return ex;
157 auto elements = resolveStructLiteralNamedArgs(sd, t, sc, i.loc, i.field[], &getExp, (size_t j) => i.value[j].loc);
158 if (!elements)
159 return err();
161 // Make a StructLiteralExp out of elements[]
162 auto sle = new StructLiteralExp(i.loc, sd, elements, t);
163 if (!sd.fill(i.loc, *elements, false))
164 return err();
165 sle.type = t;
166 auto ie = new ExpInitializer(i.loc, sle);
167 return ie.initializerSemantic(sc, t, needInterpret);
169 else if ((t.ty == Tdelegate || t.isPtrToFunction()) && i.value.length == 0)
171 const tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_;
172 /* Rewrite as empty delegate literal { }
174 Type tf = new TypeFunction(ParameterList(), null, LINK.d);
175 auto fd = new FuncLiteralDeclaration(i.loc, Loc.initial, tf, tok, null);
176 fd.fbody = new CompoundStatement(i.loc, new Statements());
177 fd.endloc = i.loc;
178 Expression e = new FuncExp(i.loc, fd);
179 auto ie = new ExpInitializer(i.loc, e);
180 return ie.initializerSemantic(sc, t, needInterpret);
182 if (t.ty != Terror)
183 error(i.loc, "a struct is not a valid initializer for a `%s`", t.toChars());
184 return err();
187 Initializer visitArray(ArrayInitializer i)
189 uint length;
190 const(uint) amax = 0x80000000;
191 bool errors = false;
192 //printf("ArrayInitializer::semantic(%s), ai: %s %p\n", t.toChars(), i.toChars(), i);
193 if (i.sem) // if semantic() already run
195 return i;
197 i.sem = true;
198 t = t.toBasetype();
199 switch (t.ty)
201 case Tsarray:
202 case Tarray:
203 break;
204 case Tvector:
205 t = t.isTypeVector().basetype;
206 break;
207 case Taarray:
208 case Tstruct: // consider implicit constructor call
210 Expression e;
211 // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int])
212 if (t.ty == Taarray || i.isAssociativeArray())
213 e = i.toAssocArrayLiteral();
214 else
215 e = i.initializerToExpression();
216 // Bugzilla 13987
217 if (!e)
219 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
220 return err();
222 auto ei = new ExpInitializer(e.loc, e);
223 return ei.initializerSemantic(sc, t, needInterpret);
225 case Tpointer:
226 if (t.nextOf().ty != Tfunction)
227 break;
228 goto default;
229 default:
230 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
231 return err();
233 i.type = t;
234 length = 0;
235 for (size_t j = 0; j < i.index.length; j++)
237 Expression idx = i.index[j];
238 if (idx)
240 sc = sc.startCTFE();
241 idx = idx.expressionSemantic(sc);
242 sc = sc.endCTFE();
243 idx = idx.ctfeInterpret();
244 i.index[j] = idx;
245 const uinteger_t idxvalue = idx.toInteger();
246 if (idxvalue >= amax)
248 error(i.loc, "array index %llu overflow", idxvalue);
249 errors = true;
251 length = cast(uint)idxvalue;
252 if (idx.op == EXP.error)
253 errors = true;
255 Initializer val = i.value[j];
256 ExpInitializer ei = val.isExpInitializer();
257 if (ei && !idx)
258 ei.expandTuples = true;
259 auto tn = t.nextOf();
260 val = val.initializerSemantic(sc, tn, needInterpret);
261 if (val.isErrorInitializer())
262 errors = true;
263 ei = val.isExpInitializer();
264 // found a tuple, expand it
265 if (ei && ei.exp.op == EXP.tuple)
267 TupleExp te = ei.exp.isTupleExp();
268 i.index.remove(j);
269 i.value.remove(j);
270 for (size_t k = 0; k < te.exps.length; ++k)
272 Expression e = (*te.exps)[k];
273 i.index.insert(j + k, cast(Expression)null);
274 i.value.insert(j + k, new ExpInitializer(e.loc, e));
276 j--;
277 continue;
279 else
281 i.value[j] = val;
283 length++;
284 if (length == 0)
286 error(i.loc, "array dimension overflow");
287 return err();
289 if (length > i.dim)
290 i.dim = length;
292 if (auto tsa = t.isTypeSArray())
294 if (sc.flags & SCOPE.Cfile && tsa.isIncomplete())
296 // Change to array of known length
297 auto tn = tsa.next.toBasetype();
298 tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, i.dim, Type.tsize_t));
299 tx = tsa; // rewrite caller's type
300 i.type = tsa; // remember for later passes
302 else
304 uinteger_t edim = tsa.dim.toInteger();
305 if (i.dim > edim)
307 error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
308 return err();
312 if (errors)
313 return err();
315 const sz = t.nextOf().size();
316 if (sz == SIZE_INVALID)
317 return err();
318 bool overflow;
319 const max = mulu(i.dim, sz, overflow);
320 if (overflow || max >= amax)
322 error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz));
323 return err();
325 //printf("returns ai: %s\n", i.toChars());
326 return i;
329 Initializer visitExp(ExpInitializer i)
331 //printf("ExpInitializer::semantic(%s), type = %s\n", i.exp.toChars(), t.toChars());
332 if (needInterpret)
333 sc = sc.startCTFE();
334 i.exp = i.exp.expressionSemantic(sc);
335 i.exp = resolveProperties(sc, i.exp);
336 if (needInterpret)
337 sc = sc.endCTFE();
338 if (i.exp.op == EXP.error)
339 return err();
340 uint olderrors = global.errors;
342 /* ImportC: convert arrays to pointers, functions to pointers to functions
344 Type tb = t.toBasetype();
345 if (tb.isTypePointer())
346 i.exp = i.exp.arrayFuncConv(sc);
348 /* Save the expression before ctfe
349 * Otherwise the error message would contain for example "&[0][0]" instead of "new int"
350 * Regression: https://issues.dlang.org/show_bug.cgi?id=21687
352 Expression currExp = i.exp;
353 if (needInterpret)
355 // If the result will be implicitly cast, move the cast into CTFE
356 // to avoid premature truncation of polysemous types.
357 // eg real [] x = [1.1, 2.2]; should use real precision.
358 if (i.exp.implicitConvTo(t) && !(sc.flags & SCOPE.Cfile))
360 i.exp = i.exp.implicitCastTo(sc, t);
362 if (!global.gag && olderrors != global.errors)
364 return i;
366 if (sc.flags & SCOPE.Cfile)
368 /* the interpreter turns (char*)"string" into &"string"[0] which then
369 * it cannot interpret. Resolve that case by doing optimize() first
371 i.exp = i.exp.optimize(WANTvalue);
372 if (i.exp.isSymOffExp())
374 /* `static variable cannot be read at compile time`
375 * https://issues.dlang.org/show_bug.cgi?id=22513
376 * Maybe this would be better addressed in ctfeInterpret()?
378 needInterpret = NeedInterpret.INITnointerpret;
381 if (needInterpret)
382 i.exp = i.exp.ctfeInterpret();
383 if (i.exp.op == EXP.voidExpression)
384 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
386 else
388 i.exp = i.exp.optimize(WANTvalue);
391 if (!global.gag && olderrors != global.errors)
393 return i; // Failed, suppress duplicate error messages
395 if (i.exp.type.isTypeTuple() && i.exp.type.isTypeTuple().arguments.length == 0)
397 Type et = i.exp.type;
398 i.exp = new TupleExp(i.exp.loc, new Expressions());
399 i.exp.type = et;
401 if (i.exp.op == EXP.type)
403 error(i.exp.loc, "initializer must be an expression, not `%s`", i.exp.toChars());
404 return err();
406 // Make sure all pointers are constants
407 if (needInterpret && hasNonConstPointers(i.exp))
409 error(i.exp.loc, "cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
410 return err();
412 Type ti = i.exp.type.toBasetype();
413 if (i.exp.op == EXP.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
415 return new ExpInitializer(i.loc, i.exp);
417 /* Look for case of initializing a static array with a too-short
418 * string literal, such as:
419 * char[5] foo = "abc";
420 * Allow this by doing an explicit cast, which will lengthen the string
421 * literal.
423 if (i.exp.op == EXP.string_ && tb.ty == Tsarray)
425 StringExp se = i.exp.isStringExp();
426 Type typeb = se.type.toBasetype();
427 TY tynto = tb.nextOf().ty;
428 if (!se.committed &&
429 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
430 se.numberOfCodeUnits(tynto) < tb.isTypeSArray().dim.toInteger())
432 i.exp = se.castTo(sc, t);
433 goto L1;
436 /* Lop off terminating 0 of initializer for:
437 * static char s[5] = "hello";
439 if (sc.flags & SCOPE.Cfile &&
440 typeb.ty == Tsarray &&
441 tynto.isSomeChar &&
442 tb.isTypeSArray().dim.toInteger() + 1 == typeb.isTypeSArray().dim.toInteger())
444 i.exp = se.castTo(sc, t);
445 goto L1;
448 /* C11 6.7.9-14..15
449 * Initialize an array of unknown size with a string.
450 * Change to static array of known size
452 if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
453 tb.isTypeSArray() && tb.isTypeSArray().isIncomplete())
455 StringExp se = i.exp.isStringExp();
456 auto ts = new TypeSArray(tb.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
457 t = typeSemantic(ts, Loc.initial, sc);
458 i.exp.type = t;
459 tx = t;
462 // Look for implicit constructor call
463 if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t))
465 StructDeclaration sd = tb.isTypeStruct().sym;
466 if (sd.ctor)
468 // Rewrite as S().ctor(exp)
469 Expression e;
470 e = new StructLiteralExp(i.loc, sd, null);
471 e = new DotIdExp(i.loc, e, Id.ctor);
472 e = new CallExp(i.loc, e, i.exp);
473 e = e.expressionSemantic(sc);
474 if (needInterpret)
475 i.exp = e.ctfeInterpret();
476 else
477 i.exp = e.optimize(WANTvalue);
479 else if (search_function(sd, Id.call))
481 /* https://issues.dlang.org/show_bug.cgi?id=1547
483 * Look for static opCall
485 * Rewrite as:
486 * i.exp = typeof(sd).opCall(arguments)
489 Expression e = typeDotIdExp(i.loc, sd.type, Id.call);
490 e = new CallExp(i.loc, e, i.exp);
491 e = e.expressionSemantic(sc);
492 e = resolveProperties(sc, e);
493 if (needInterpret)
494 i.exp = e.ctfeInterpret();
495 else
496 i.exp = e.optimize(WANTvalue);
500 // Look for the case of statically initializing an array with a single member.
501 // Recursively strip static array / enum layers until a compatible element is found,
502 // and return an `ArrayLiteralExp` repeating the initializer, or `null` if no match found
503 // int[2][3] = 7 => [[7, 7], [7, 7], [7, 7]]
504 // int[2] = new Object => null
505 Expression sarrayRepeat(Type tb)
507 auto tsa = tb.isTypeSArray();
508 if (!tsa)
509 return null;
511 // printf("i.exp = %s, tsa = %s\n", i.exp.toChars(), tsa.toChars());
512 Expression elem = null;
513 if (i.exp.implicitConvTo(tb.nextOf()))
514 elem = i.exp.implicitCastTo(sc, tb.nextOf());
515 else if (auto ae = sarrayRepeat(tb.nextOf().toBasetype()))
516 elem = ae;
517 else
518 return null;
520 auto arrayElements = new Expressions(cast(size_t) tsa.dim.toInteger());
521 foreach (ref e; *arrayElements)
522 e = elem;
523 return new ArrayLiteralExp(i.exp.loc, tb, elem, arrayElements);
526 if (auto sa = sarrayRepeat(tb))
528 // printf("sa = %s\n", sa.toChars());
529 i.exp = sa;
533 auto tta = t.isTypeSArray();
534 if (i.exp.implicitConvTo(t))
536 i.exp = i.exp.implicitCastTo(sc, t);
538 else if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
539 tta && (tta.next.ty == Tint8 || tta.next.ty == Tuns8) &&
540 ti.ty == Tsarray && ti.nextOf().ty == Tchar)
542 /* unsigned char bbb[1] = "";
543 * signed char ccc[1] = "";
545 i.exp = i.exp.castTo(sc, t);
547 else
549 auto tba = tb.isTypeSArray();
550 // Look for mismatch of compile-time known length to emit
551 // better diagnostic message, as same as AssignExp::semantic.
552 if (tba && i.exp.implicitConvTo(tba.next.arrayOf()) > MATCH.nomatch)
554 uinteger_t dim1 = tba.dim.toInteger();
555 uinteger_t dim2 = dim1;
556 if (auto ale = i.exp.isArrayLiteralExp())
558 dim2 = ale.elements ? ale.elements.length : 0;
560 else if (auto se = i.exp.isSliceExp())
562 if (Type tx = toStaticArrayType(se))
563 dim2 = tx.isTypeSArray().dim.toInteger();
565 if (dim1 != dim2)
567 error(i.exp.loc, "mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
568 i.exp = ErrorExp.get();
571 Type et = i.exp.type;
572 const errors = global.startGagging();
573 i.exp = i.exp.implicitCastTo(sc, t);
574 if (global.endGagging(errors))
575 error(currExp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toChars(), et.toChars(), t.toChars());
579 if (i.exp.op == EXP.error)
581 return i;
583 if (needInterpret)
584 i.exp = i.exp.ctfeInterpret();
585 else
586 i.exp = i.exp.optimize(WANTvalue);
587 //printf("-ExpInitializer::semantic(): "); i.exp.print();
588 return i;
591 Initializer visitC(CInitializer ci)
593 //printf("CInitializer::semantic() tx: %s t: %s ci: %s\n", (tx ? tx.toChars() : "".ptr), t.toChars(), ci.toChars());
594 /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer
596 t = t.toBasetype();
598 if (auto tv = t.isTypeVector())
599 t = tv.basetype;
601 /* If `{ expression }` return the expression initializer
603 ExpInitializer isBraceExpression()
605 auto dil = ci.initializerList[];
606 return (dil.length == 1 && !dil[0].designatorList)
607 ? dil[0].initializer.isExpInitializer()
608 : null;
611 /********************************
613 bool overlaps(VarDeclaration field, VarDeclaration[] fields, StructInitializer si)
615 foreach (fld; fields)
617 if (field.isOverlappedWith(fld))
619 // look for initializer corresponding with fld
620 foreach (i, ident; si.field[])
622 if (ident == fld.ident && si.value[i])
623 return true; // already an initializer for `field`
627 return false;
630 /* Run semantic on ExpInitializer, see if it represents entire struct ts
632 bool representsStruct(ExpInitializer ei, TypeStruct ts)
634 if (needInterpret)
635 sc = sc.startCTFE();
636 ei.exp = ei.exp.expressionSemantic(sc);
637 ei.exp = resolveProperties(sc, ei.exp);
638 if (needInterpret)
639 sc = sc.endCTFE();
640 return ei.exp.implicitConvTo(ts) != MATCH.nomatch; // initializer represents the entire struct
643 /* If { } are omitted from substructs, use recursion to reconstruct where
644 * brackets go
645 * Params:
646 * ts = substruct to initialize
647 * index = index into ci.initializer, updated
648 * Returns: struct initializer for this substruct
650 Initializer subStruct()(TypeStruct ts, ref size_t index)
652 //printf("subStruct(ts: %s, index %d)\n", ts.toChars(), cast(int)index);
654 auto si = new StructInitializer(ci.loc);
655 StructDeclaration sd = ts.sym;
656 sd.size(ci.loc);
657 if (sd.sizeok != Sizeok.done)
659 index = ci.initializerList.length;
660 return err();
662 const nfields = sd.fields.length;
664 foreach (fieldi; 0 .. nfields)
666 if (index >= ci.initializerList.length)
667 break; // ran out of initializers
668 auto di = ci.initializerList[index];
669 if (di.designatorList && fieldi != 0)
670 break; // back to top level
671 else
673 VarDeclaration field;
674 while (1) // skip field if it overlaps with previously seen fields
676 field = sd.fields[fieldi];
677 ++fieldi;
678 if (!overlaps(field, sd.fields[], si))
679 break;
680 if (fieldi == nfields)
681 break;
683 auto tn = field.type.toBasetype();
684 auto tnsa = tn.isTypeSArray();
685 auto tns = tn.isTypeStruct();
686 auto ix = di.initializer;
687 if (tnsa && ix.isExpInitializer())
689 ExpInitializer ei = ix.isExpInitializer();
690 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
692 si.addInit(field.ident, ei);
693 ++index;
695 else
696 si.addInit(field.ident, subArray(tnsa, index)); // fwd ref of subArray is why subStruct is a template
698 else if (tns && ix.isExpInitializer())
700 /* Disambiguate between an exp representing the entire
701 * struct, and an exp representing the first field of the struct
703 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
705 si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
706 ++index;
708 else // field initializers for struct
709 si.addInit(field.ident, subStruct(tns, index)); // the first field
711 else
713 si.addInit(field.ident, ix);
714 ++index;
718 //printf("subStruct() returns ai: %s, index: %d\n", si.toChars(), cast(int)index);
719 return si;
722 /* If { } are omitted from subarrays, use recursion to reconstruct where
723 * brackets go
724 * Params:
725 * tsa = subarray to initialize
726 * index = index into ci.initializer, updated
727 * Returns: array initializer for this subarray
729 Initializer subArray(TypeSArray tsa, ref size_t index)
731 //printf("array(tsa: %s, index %d)\n", tsa.toChars(), cast(int)index);
732 if (tsa.isIncomplete())
734 // C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
735 assert(0); // should have been detected by parser
738 auto tnsa = tsa.nextOf().toBasetype().isTypeSArray();
740 auto ai = new ArrayInitializer(ci.loc);
741 ai.isCarray = true;
743 foreach (n; 0 .. cast(size_t)tsa.dim.toInteger())
745 if (index >= ci.initializerList.length)
746 break; // ran out of initializers
747 auto di = ci.initializerList[index];
748 if (di.designatorList)
749 break; // back to top level
750 else if (tnsa && di.initializer.isExpInitializer())
752 ExpInitializer ei = di.initializer.isExpInitializer();
753 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
755 ai.addInit(null, ei);
756 ++index;
758 else
759 ai.addInit(null, subArray(tnsa, index));
761 else
763 ai.addInit(null, di.initializer);
764 ++index;
767 //printf("array() returns ai: %s, index: %d\n", ai.toChars(), cast(int)index);
768 return ai;
771 if (auto ts = t.isTypeStruct())
773 auto si = new StructInitializer(ci.loc);
774 StructDeclaration sd = ts.sym;
775 sd.size(ci.loc); // run semantic() on sd to get fields
776 if (sd.sizeok != Sizeok.done)
778 return err();
780 const nfields = sd.fields.length;
781 size_t fieldi = 0;
783 Loop1:
784 for (size_t index = 0; index < ci.initializerList.length; )
786 CInitializer cprev;
788 DesigInit di = ci.initializerList[index];
789 Designators* dlist = di.designatorList;
790 if (dlist)
792 const length = (*dlist).length;
793 if (length == 0 || !(*dlist)[0].ident)
795 error(ci.loc, "`.identifier` expected for C struct field initializer `%s`", toChars(ci));
796 return err();
798 if (length > 1)
800 error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", toChars(ci));
801 return err();
803 auto id = (*dlist)[0].ident;
804 foreach (k, f; sd.fields[]) // linear search for now
806 if (f.ident == id)
808 fieldi = k;
809 si.addInit(id, di.initializer);
810 ++fieldi;
811 ++index;
812 continue Loop1;
815 if (cprev)
817 /* The peeling didn't work, so unpeel it
819 ci = cprev;
820 di = ci.initializerList[index];
821 goto L2;
823 error(ci.loc, "`.%s` is not a field of `%s`\n", id.toChars(), sd.toChars());
824 return err();
826 else
828 if (fieldi == nfields)
829 break;
830 if (index == 0 && ci.initializerList.length == 1 && di.initializer.isCInitializer())
832 /* Try peeling off this set of { } and see if it works
834 cprev = ci;
835 ci = di.initializer.isCInitializer();
836 goto L1;
840 VarDeclaration field;
841 while (1) // skip field if it overlaps with previously seen fields
843 field = sd.fields[fieldi];
844 ++fieldi;
845 if (!overlaps(field, sd.fields[], si))
846 break;
847 if (fieldi == nfields)
848 break;
850 auto tn = field.type.toBasetype();
851 auto tnsa = tn.isTypeSArray();
852 auto tns = tn.isTypeStruct();
853 auto ix = di.initializer;
854 if (tnsa && ix.isExpInitializer())
856 ExpInitializer ei = ix.isExpInitializer();
857 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
859 si.addInit(field.ident, ei);
860 ++index;
862 else
863 si.addInit(field.ident, subArray(tnsa, index));
865 else if (tns && ix.isExpInitializer())
867 /* Disambiguate between an exp representing the entire
868 * struct, and an exp representing the first field of the struct
870 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
872 si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
873 ++index;
875 else // field initializers for struct
876 si.addInit(field.ident, subStruct(tns, index)); // the first field
878 else
880 si.addInit(field.ident, di.initializer);
881 ++index;
885 return initializerSemantic(si, sc, t, needInterpret);
887 else if (auto ta = t.isTypeSArray())
889 auto tn = t.nextOf().toBasetype(); // element type of array
891 /* If it's an array of integral being initialized by `{ string }`
892 * replace with `string`
894 if (tn.isintegral())
896 if (ExpInitializer ei = isBraceExpression())
898 if (ei.exp.isStringExp())
899 return ei.initializerSemantic(sc, t, needInterpret);
903 auto tnsa = tn.isTypeSArray(); // array of array
904 auto tns = tn.isTypeStruct(); // array of struct
906 auto ai = new ArrayInitializer(ci.loc);
907 ai.isCarray = true;
908 for (size_t index = 0; index < ci.initializerList.length; )
910 auto di = ci.initializerList[index];
911 if (auto dlist = di.designatorList)
913 const length = (*dlist).length;
914 if (length == 0 || !(*dlist)[0].exp)
916 error(ci.loc, "`[ constant-expression ]` expected for C array element initializer `%s`", toChars(ci));
917 return err();
919 if (length > 1)
921 error(ci.loc, "only 1 designator currently allowed for C array element initializer `%s`", toChars(ci));
922 return err();
924 //printf("tn: %s, di.initializer: %s\n", tn.toChars(), di.initializer.toChars());
925 auto ix = di.initializer;
926 if (tnsa && ix.isExpInitializer())
928 // Wrap initializer in [ ]
929 auto ain = new ArrayInitializer(ci.loc);
930 ain.addInit(null, di.initializer);
931 ix = ain;
932 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
933 ++index;
935 else if (tns && ix.isExpInitializer())
937 /* Disambiguate between an exp representing the entire
938 * struct, and an exp representing the first field of the struct
940 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
942 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
943 ++index;
945 else // field initializers for struct
946 ai.addInit((*dlist)[0].exp, subStruct(tns, index)); // the first field
948 else
950 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
951 ++index;
954 else if (tnsa && di.initializer.isExpInitializer())
956 ExpInitializer ei = di.initializer.isExpInitializer();
957 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
959 ai.addInit(null, ei);
960 ++index;
962 else
963 ai.addInit(null, subArray(tnsa, index));
965 else if (tns && di.initializer.isExpInitializer())
967 /* Disambiguate between an exp representing the entire
968 * struct, and an exp representing the first field of the struct
970 if (representsStruct(di.initializer.isExpInitializer(), tns)) // initializer represents the entire struct
972 ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
973 ++index;
975 else // field initializers for struct
976 ai.addInit(null, subStruct(tns, index)); // the first field
978 else
980 ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
981 ++index;
984 return initializerSemantic(ai, sc, tx, needInterpret);
986 else if (ExpInitializer ei = isBraceExpression())
988 return visitExp(ei);
990 else
992 error(ci.loc, "unrecognized C initializer `%s`", toChars(ci));
993 return err();
997 mixin VisitInitializer!Initializer visit;
998 auto result = visit.VisitInitializer(init);
999 return (result !is null) ? result : new ErrorInitializer();
1002 /***********************
1003 * Translate init to an `Expression` in order to infer the type.
1004 * Params:
1005 * init = `Initializer` AST node
1006 * sc = context
1007 * Returns:
1008 * an equivalent `ExpInitializer` if successful, or `ErrorInitializer` if it cannot be translated
1010 Initializer inferType(Initializer init, Scope* sc)
1012 Initializer visitVoid(VoidInitializer i)
1014 error(i.loc, "cannot infer type from void initializer");
1015 return new ErrorInitializer();
1018 Initializer visitError(ErrorInitializer i)
1020 return i;
1023 Initializer visitStruct(StructInitializer i)
1025 error(i.loc, "cannot infer type from struct initializer");
1026 return new ErrorInitializer();
1029 Initializer visitArray(ArrayInitializer init)
1031 //printf("ArrayInitializer::inferType() %s\n", toChars());
1032 Expressions* keys = null;
1033 Expressions* values;
1034 if (init.isAssociativeArray())
1036 keys = new Expressions(init.value.length);
1037 values = new Expressions(init.value.length);
1038 for (size_t i = 0; i < init.value.length; i++)
1040 Expression e = init.index[i];
1041 if (!e)
1042 goto Lno;
1043 (*keys)[i] = e;
1044 Initializer iz = init.value[i];
1045 if (!iz)
1046 goto Lno;
1047 iz = iz.inferType(sc);
1048 if (iz.isErrorInitializer())
1050 return iz;
1052 (*values)[i] = iz.isExpInitializer().exp;
1053 assert(!(*values)[i].isErrorExp());
1055 Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
1056 auto ei = new ExpInitializer(init.loc, e);
1057 return ei.inferType(sc);
1059 else
1061 auto elements = new Expressions(init.value.length);
1062 elements.zero();
1063 for (size_t i = 0; i < init.value.length; i++)
1065 assert(!init.index[i]); // already asserted by isAssociativeArray()
1066 Initializer iz = init.value[i];
1067 if (!iz)
1068 goto Lno;
1069 iz = iz.inferType(sc);
1070 if (iz.isErrorInitializer())
1072 return iz;
1074 (*elements)[i] = iz.isExpInitializer().exp;
1075 assert(!(*elements)[i].isErrorExp());
1077 Expression e = new ArrayLiteralExp(init.loc, null, elements);
1078 auto ei = new ExpInitializer(init.loc, e);
1079 return ei.inferType(sc);
1081 Lno:
1082 if (keys)
1084 error(init.loc, "not an associative array initializer");
1086 else
1088 error(init.loc, "cannot infer type from array initializer");
1090 return new ErrorInitializer();
1093 Initializer visitExp(ExpInitializer init)
1095 //printf("ExpInitializer::inferType() %s\n", init.toChars());
1096 init.exp = init.exp.expressionSemantic(sc);
1098 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1099 if (init.exp.op == EXP.type)
1100 init.exp = resolveAliasThis(sc, init.exp);
1102 init.exp = resolveProperties(sc, init.exp);
1103 if (auto se = init.exp.isScopeExp())
1105 TemplateInstance ti = se.sds.isTemplateInstance();
1106 if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
1107 error(se.loc, "cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
1108 else
1109 error(se.loc, "cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
1110 return new ErrorInitializer();
1113 // Give error for overloaded function addresses
1114 bool hasOverloads;
1115 if (auto f = isFuncAddress(init.exp, &hasOverloads))
1117 if (f.checkForwardRef(init.loc))
1119 return new ErrorInitializer();
1121 if (hasOverloads && !f.isUnique())
1123 error(init.exp.loc, "cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1124 return new ErrorInitializer();
1127 if (auto ae = init.exp.isAddrExp())
1129 if (ae.e1.op == EXP.overloadSet)
1131 error(init.exp.loc, "cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1132 return new ErrorInitializer();
1135 if (init.exp.isErrorExp())
1137 return new ErrorInitializer();
1139 if (!init.exp.type)
1141 return new ErrorInitializer();
1143 return init;
1146 Initializer visitC(CInitializer i)
1148 //printf("CInitializer.inferType()\n");
1149 error(i.loc, "TODO C inferType initializers not supported yet");
1150 return new ErrorInitializer();
1153 mixin VisitInitializer!Initializer visit;
1154 auto result = visit.VisitInitializer(init);
1155 return (result !is null) ? result : new ErrorInitializer();
1158 /***********************
1159 * Translate init to an `Expression`.
1160 * Params:
1161 * init = `Initializer` AST node
1162 * itype = if not `null`, type to coerce expression to
1163 * isCfile = default initializers are different with C
1164 * Returns:
1165 * `Expression` created, `null` if cannot, `ErrorExp` for other errors
1167 extern (C++) Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false)
1169 //printf("initializerToExpression() isCfile: %d\n", isCfile);
1171 Expression visitVoid(VoidInitializer)
1173 return null;
1176 Expression visitError(ErrorInitializer)
1178 return ErrorExp.get();
1181 /***************************************
1182 * This works by transforming a struct initializer into
1183 * a struct literal. In the future, the two should be the
1184 * same thing.
1186 Expression visitStruct(StructInitializer)
1188 // cannot convert to an expression without target 'ad'
1189 return null;
1192 /********************************
1193 * If possible, convert array initializer to array literal.
1194 * Otherwise return NULL.
1196 Expression visitArray(ArrayInitializer init)
1198 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
1199 //static int i; if (++i == 2) assert(0);
1200 uint edim; // the length of the resulting array literal
1201 const(uint) amax = 0x80000000;
1202 Type t = null; // type of the array literal being initialized
1203 if (init.type)
1205 if (init.type == Type.terror)
1207 return ErrorExp.get();
1209 t = init.type.toBasetype();
1210 switch (t.ty)
1212 case Tvector:
1213 t = t.isTypeVector().basetype;
1214 goto case Tsarray;
1216 case Tsarray:
1217 uinteger_t adim = t.isTypeSArray().dim.toInteger();
1218 if (adim >= amax)
1219 return null;
1220 edim = cast(uint)adim;
1221 break;
1223 case Tpointer:
1224 case Tarray:
1225 edim = init.dim;
1226 break;
1228 default:
1229 assert(0);
1232 else
1234 /* Calculate the length of the array literal
1236 edim = cast(uint)init.value.length;
1237 size_t j = 0;
1238 foreach (i; 0 .. init.value.length)
1240 if (auto e = init.index[i])
1242 if (e.op == EXP.int64)
1244 const uinteger_t idxval = e.toInteger();
1245 if (idxval >= amax)
1246 return null;
1247 j = cast(size_t)idxval;
1249 else
1250 return null;
1252 ++j;
1253 if (j > edim)
1254 edim = cast(uint)j;
1258 auto elements = new Expressions(edim);
1259 elements.zero();
1260 size_t j = 0;
1261 foreach (i; 0 .. init.value.length)
1263 if (auto e = init.index[i])
1264 j = cast(size_t)e.toInteger();
1265 assert(j < edim);
1266 if (Initializer iz = init.value[i])
1268 if (Expression ex = iz.initializerToExpression(null, isCfile))
1270 (*elements)[j] = ex;
1271 ++j;
1273 else
1274 return null;
1276 else
1277 return null;
1280 /* Fill in any missing elements with the default initializer
1282 Expression defaultInit = null; // lazily create it
1283 foreach (ref element; (*elements)[0 .. edim])
1285 if (!element)
1287 if (!init.type) // don't know what type to use
1288 return null;
1289 if (!defaultInit)
1290 defaultInit = (cast(TypeNext)t).next.defaultInit(Loc.initial, isCfile);
1291 element = defaultInit;
1295 /* Expand any static array initializers that are a single expression
1296 * into an array of them
1297 * e => [e, e, ..., e, e]
1299 if (t)
1301 Type tn = t.nextOf().toBasetype();
1302 if (tn.ty == Tsarray)
1304 const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger();
1305 Type te = tn.nextOf().toBasetype();
1306 foreach (ref e; *elements)
1308 if (te.equals(e.type))
1310 auto elements2 = new Expressions(dim);
1311 foreach (ref e2; *elements2)
1312 e2 = e;
1313 e = new ArrayLiteralExp(e.loc, tn, elements2);
1319 /* If any elements are errors, then the whole thing is an error
1321 foreach (e; (*elements)[0 .. edim])
1323 if (e.op == EXP.error)
1325 return e;
1329 Expression e = new ArrayLiteralExp(init.loc, init.type, elements);
1330 return e;
1333 Expression visitExp(ExpInitializer i)
1335 if (itype)
1337 //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
1338 Type tb = itype.toBasetype();
1339 Expression e = (i.exp.op == EXP.construct || i.exp.op == EXP.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
1340 if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
1342 TypeSArray tsa = cast(TypeSArray)tb;
1343 size_t d = cast(size_t)tsa.dim.toInteger();
1344 auto elements = new Expressions(d);
1345 for (size_t j = 0; j < d; j++)
1346 (*elements)[j] = e;
1347 auto ae = new ArrayLiteralExp(e.loc, itype, elements);
1348 return ae;
1351 return i.exp;
1354 Expression visitC(CInitializer i)
1356 //printf("CInitializer.initializerToExpression(null, true)\n");
1357 return null;
1360 mixin VisitInitializer!Expression visit;
1361 return visit.VisitInitializer(init);
1365 /**************************************
1366 * Determine if expression has non-constant pointers, or more precisely,
1367 * a pointer that CTFE cannot handle.
1368 * Params:
1369 * e = expression to check
1370 * Returns:
1371 * true if it has non-constant pointers
1373 private bool hasNonConstPointers(Expression e)
1375 static bool checkArray(Expressions* elems)
1377 foreach (e; *elems)
1379 if (e && hasNonConstPointers(e))
1380 return true;
1382 return false;
1385 if (e.type.ty == Terror)
1386 return false;
1387 if (e.op == EXP.null_)
1388 return false;
1389 if (auto se = e.isStructLiteralExp())
1391 return checkArray(se.elements);
1393 if (auto ae = e.isArrayLiteralExp())
1395 if (!ae.type.nextOf().hasPointers())
1396 return false;
1397 return checkArray(ae.elements);
1399 if (auto ae = e.isAssocArrayLiteralExp())
1401 if (ae.type.nextOf().hasPointers() && checkArray(ae.values))
1402 return true;
1403 if (ae.type.isTypeAArray().index.hasPointers())
1404 return checkArray(ae.keys);
1405 return false;
1407 if (auto ae = e.isAddrExp())
1409 if (ae.type.nextOf().isImmutable() || ae.type.nextOf().isConst())
1411 return false;
1413 if (auto se = ae.e1.isStructLiteralExp())
1415 if (!(se.stageflags & stageSearchPointers))
1417 const old = se.stageflags;
1418 se.stageflags |= stageSearchPointers;
1419 bool ret = checkArray(se.elements);
1420 se.stageflags = old;
1421 return ret;
1423 else
1425 return false;
1428 return true;
1430 if (e.type.ty == Tpointer && !e.type.isPtrToFunction())
1432 if (e.op == EXP.symbolOffset) // address of a global is OK
1433 return false;
1434 if (e.op == EXP.int64) // cast(void *)int is OK
1435 return false;
1436 if (e.op == EXP.string_) // "abc".ptr is OK
1437 return false;
1438 return true;
1440 return false;
1444 Given the names and values of a `StructInitializer` or `CallExp`,
1445 resolve it to a list of expressions to construct a `StructLiteralExp`.
1447 Params:
1448 sd = struct
1449 t = type of struct (potentially including qualifiers such as `const` or `immutable`)
1450 sc = scope of the expression initializing the struct
1451 iloc = location of expression initializing the struct
1452 names = identifiers passed in argument list, `null` entries for positional arguments
1453 getExp = function that, given an index into `names` and destination type, returns the initializing expression
1454 getLoc = function that, given an index into `names`, returns a location for error messages
1456 Returns: list of expressions ordered to the struct's fields, or `null` on error
1458 Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* sc,
1459 Loc iloc, Identifier[] names, scope Expression delegate(size_t i, Type fieldType) getExp,
1460 scope Loc delegate(size_t i) getLoc
1463 //expandTuples for non-identity arguments?
1464 const nfields = sd.nonHiddenFields();
1465 auto elements = new Expressions(nfields);
1466 auto elems = (*elements)[];
1467 foreach (ref elem; elems)
1468 elem = null;
1470 // Run semantic for explicitly given initializers
1471 // TODO: this part is slightly different from StructLiteralExp::semantic.
1472 bool errors = false;
1473 size_t fieldi = 0;
1474 foreach (j, id; names)
1476 const argLoc = getLoc(j);
1477 if (id)
1479 // Determine `fieldi` that `id` matches
1480 Dsymbol s = sd.search(iloc, id);
1481 if (!s)
1483 s = sd.search_correct(id);
1484 if (s)
1485 error(argLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars());
1486 else
1487 error(argLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars());
1488 return null;
1490 s.checkDeprecated(iloc, sc);
1491 s = s.toAlias();
1493 // Find out which field index `s` is
1494 for (fieldi = 0; 1; fieldi++)
1496 if (fieldi >= nfields)
1498 error(iloc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars());
1499 return null;
1501 if (s == sd.fields[fieldi])
1502 break;
1505 if (nfields == 0)
1507 error(argLoc, "initializer provided for struct `%s` with no fields", sd.toChars());
1508 return null;
1510 if (j >= nfields)
1512 error(argLoc, "too many initializers for `%s` with %d field%s", sd.toChars(),
1513 cast(int) nfields, nfields != 1 ? "s".ptr : "".ptr);
1514 return null;
1517 VarDeclaration vd = sd.fields[fieldi];
1518 if (elems[fieldi])
1520 error(argLoc, "duplicate initializer for field `%s`", vd.toChars());
1521 errors = true;
1522 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
1523 ++fieldi;
1524 continue;
1527 // Check for @safe violations
1528 if (vd.type.hasPointers)
1530 if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize ||
1531 (vd.offset & (target.ptrsize - 1))))
1533 if (sc.setUnsafe(false, argLoc,
1534 "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, vd))
1536 errors = true;
1537 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
1538 ++fieldi;
1539 continue;
1544 // Check for overlapping initializations (can happen with unions)
1545 foreach (k, v2; sd.fields[0 .. nfields])
1547 if (vd.isOverlappedWith(v2) && elems[k])
1549 error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
1550 enum errorMsg = "`struct` initializers that contain anonymous unions" ~
1551 " must initialize only the first member of a `union`. All subsequent" ~
1552 " non-overlapping fields are default initialized";
1553 if (!sd.isUnionDeclaration())
1554 .errorSupplemental(elems[k].loc, errorMsg);
1555 errors = true;
1556 continue;
1560 assert(sc);
1562 auto ex = getExp(j, vd.type);
1564 if (ex.op == EXP.error)
1566 errors = true;
1567 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
1568 ++fieldi;
1569 continue;
1572 elems[fieldi] = doCopyOrMove(sc, ex);
1573 ++fieldi;
1575 if (errors)
1576 return null;
1578 return elements;