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
14 import core.stdc.stdio;
15 import core.checkedint;
19 import dmd.arraytypes;
22 import dmd.declaration;
28 import dmd.expression;
29 import dmd.expressionsem;
33 import dmd.identifier;
44 /********************************
45 * If possible, convert array initializer to associative array initializer.
48 * ai = array initializer to be converted
51 * The converted associative array initializer or ErrorExp if `ai`
52 * is not an associative array initializer.
54 Expression toAssocArrayLiteral(ArrayInitializer ai)
57 //printf("ArrayInitializer::toAssocArrayInitializer()\n");
58 //static int i; if (++i == 2) assert(0);
59 const dim = ai.value.length;
60 auto keys = new Expressions(dim);
61 auto values = new Expressions(dim);
62 for (size_t i = 0; i < dim; i++)
68 Initializer iz = ai.value[i];
71 e = iz.initializerToExpression();
76 e = new AssocArrayLiteralExp(ai.loc, keys, values);
79 error(ai.loc, "not an associative array initializer");
80 return ErrorExp.get();
83 /******************************************
84 * Perform semantic analysis on init.
86 * init = Initializer AST node
88 * tx = type that the initializer needs to become. If tx is an incomplete
89 * type and the initializer completes it, it is updated to be the
90 * complete type. ImportC has incomplete types
91 * needInterpret = if CTFE needs to be run on this,
92 * such as if it is the initializer for a const declaration
94 * `Initializer` with completed semantic analysis, `ErrorInitializer` if errors
97 extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
101 static Initializer err()
103 return new ErrorInitializer();
106 Initializer visitVoid(VoidInitializer i)
112 Initializer visitError(ErrorInitializer i)
117 Initializer visitStruct(StructInitializer i)
119 //printf("StructInitializer::semantic(t = %s) %s\n", t.toChars(), i.toChars());
120 /* This works by replacing the StructInitializer with an ExpInitializer.
123 if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct)
124 t = t.nextOf().toBasetype();
125 if (auto ts = t.isTypeStruct())
127 StructDeclaration sd = ts.sym;
128 // check if the sd has a regular ctor (user defined non-copy ctor)
129 // that is not disabled.
130 if (sd.hasRegularCtor(true))
132 error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars());
136 if (sd.sizeok != Sizeok.done)
138 const nfields = sd.nonHiddenFields();
139 //expandTuples for non-identity arguments?
140 auto elements = new Expressions(nfields);
141 auto elems = (*elements)[];
142 foreach (ref elem; elems)
145 // Run semantic for explicitly given initializers
146 // TODO: this part is slightly different from StructLiteralExp::semantic.
149 foreach (j, id; i.field[])
153 /* Determine `fieldi` that `id` matches
155 Dsymbol s = sd.search(i.loc, id);
158 s = sd.search_correct(id);
159 const initLoc = i.value[j].loc;
161 error(initLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars());
163 error(initLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars());
166 s.checkDeprecated(i.loc, sc);
169 // Find out which field index `s` is
170 for (fieldi = 0; 1; fieldi++)
172 if (fieldi >= nfields)
174 error(i.loc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars());
177 if (s == sd.fields[fieldi])
183 error(i.value[j].loc, "too many initializers for `%s`", sd.toChars());
187 VarDeclaration vd = sd.fields[fieldi];
190 error(i.value[j].loc, "duplicate initializer for field `%s`", vd.toChars());
192 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
197 // Check for @safe violations
198 if (vd.type.hasPointers)
200 if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize ||
201 (vd.offset & (target.ptrsize - 1))))
203 if (sc.setUnsafe(false, i.value[j].loc,
204 "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, vd))
207 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
214 // Check for overlapping initializations (can happen with unions)
215 foreach (k, v2; sd.fields[0 .. nfields])
217 if (vd.isOverlappedWith(v2) && elems[k])
219 error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
225 // Convert initializer to Expression `ex`
227 auto tm = vd.type.addMod(t.mod);
228 auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret);
229 auto ex = iz.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
230 if (ex.op == EXP.error)
233 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
239 elems[fieldi] = doCopyOrMove(sc, ex);
245 // Make a StructLiteralExp out of elements[]
246 auto sle = new StructLiteralExp(i.loc, sd, elements, t);
247 if (!sd.fill(i.loc, *elements, false))
250 auto ie = new ExpInitializer(i.loc, sle);
251 return ie.initializerSemantic(sc, t, needInterpret);
253 else if ((t.ty == Tdelegate || t.isPtrToFunction()) && i.value.length == 0)
255 const tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_;
256 /* Rewrite as empty delegate literal { }
258 Type tf = new TypeFunction(ParameterList(), null, LINK.d);
259 auto fd = new FuncLiteralDeclaration(i.loc, Loc.initial, tf, tok, null);
260 fd.fbody = new CompoundStatement(i.loc, new Statements());
262 Expression e = new FuncExp(i.loc, fd);
263 auto ie = new ExpInitializer(i.loc, e);
264 return ie.initializerSemantic(sc, t, needInterpret);
267 error(i.loc, "a struct is not a valid initializer for a `%s`", t.toChars());
271 Initializer visitArray(ArrayInitializer i)
274 const(uint) amax = 0x80000000;
276 //printf("ArrayInitializer::semantic(%s), ai: %s %p\n", t.toChars(), i.toChars(), i);
277 if (i.sem) // if semantic() already run
289 t = t.isTypeVector().basetype;
292 case Tstruct: // consider implicit constructor call
295 // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int])
296 if (t.ty == Taarray || i.isAssociativeArray())
297 e = i.toAssocArrayLiteral();
299 e = i.initializerToExpression();
303 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
306 auto ei = new ExpInitializer(e.loc, e);
307 return ei.initializerSemantic(sc, t, needInterpret);
310 if (t.nextOf().ty != Tfunction)
314 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
319 for (size_t j = 0; j < i.index.length; j++)
321 Expression idx = i.index[j];
325 idx = idx.expressionSemantic(sc);
327 idx = idx.ctfeInterpret();
329 const uinteger_t idxvalue = idx.toInteger();
330 if (idxvalue >= amax)
332 error(i.loc, "array index %llu overflow", idxvalue);
335 length = cast(uint)idxvalue;
336 if (idx.op == EXP.error)
339 Initializer val = i.value[j];
340 ExpInitializer ei = val.isExpInitializer();
342 ei.expandTuples = true;
343 auto tn = t.nextOf();
344 val = val.initializerSemantic(sc, tn, needInterpret);
345 if (val.isErrorInitializer())
347 ei = val.isExpInitializer();
348 // found a tuple, expand it
349 if (ei && ei.exp.op == EXP.tuple)
351 TupleExp te = ei.exp.isTupleExp();
354 for (size_t k = 0; k < te.exps.length; ++k)
356 Expression e = (*te.exps)[k];
357 i.index.insert(j + k, cast(Expression)null);
358 i.value.insert(j + k, new ExpInitializer(e.loc, e));
370 error(i.loc, "array dimension overflow");
376 if (auto tsa = t.isTypeSArray())
378 if (sc.flags & SCOPE.Cfile && tsa.isIncomplete())
380 // Change to array of known length
381 auto tn = tsa.next.toBasetype();
382 tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, i.dim, Type.tsize_t));
383 tx = tsa; // rewrite caller's type
384 i.type = tsa; // remember for later passes
388 uinteger_t edim = tsa.dim.toInteger();
391 error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
399 const sz = t.nextOf().size();
400 if (sz == SIZE_INVALID)
403 const max = mulu(i.dim, sz, overflow);
404 if (overflow || max >= amax)
406 error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz));
409 //printf("returns ai: %s\n", i.toChars());
413 Initializer visitExp(ExpInitializer i)
415 //printf("ExpInitializer::semantic(%s), type = %s\n", i.exp.toChars(), t.toChars());
418 i.exp = i.exp.expressionSemantic(sc);
419 i.exp = resolveProperties(sc, i.exp);
422 if (i.exp.op == EXP.error)
424 uint olderrors = global.errors;
426 /* ImportC: convert arrays to pointers, functions to pointers to functions
428 Type tb = t.toBasetype();
429 if (tb.isTypePointer())
430 i.exp = i.exp.arrayFuncConv(sc);
432 /* Save the expression before ctfe
433 * Otherwise the error message would contain for example "&[0][0]" instead of "new int"
434 * Regression: https://issues.dlang.org/show_bug.cgi?id=21687
436 Expression currExp = i.exp;
439 // If the result will be implicitly cast, move the cast into CTFE
440 // to avoid premature truncation of polysemous types.
441 // eg real [] x = [1.1, 2.2]; should use real precision.
442 if (i.exp.implicitConvTo(t) && !(sc.flags & SCOPE.Cfile))
444 i.exp = i.exp.implicitCastTo(sc, t);
446 if (!global.gag && olderrors != global.errors)
450 if (sc.flags & SCOPE.Cfile)
452 /* the interpreter turns (char*)"string" into &"string"[0] which then
453 * it cannot interpret. Resolve that case by doing optimize() first
455 i.exp = i.exp.optimize(WANTvalue);
456 if (i.exp.isSymOffExp())
458 /* `static variable cannot be read at compile time`
459 * https://issues.dlang.org/show_bug.cgi?id=22513
460 * Maybe this would be better addressed in ctfeInterpret()?
462 needInterpret = NeedInterpret.INITnointerpret;
466 i.exp = i.exp.ctfeInterpret();
467 if (i.exp.op == EXP.voidExpression)
468 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
472 i.exp = i.exp.optimize(WANTvalue);
475 if (!global.gag && olderrors != global.errors)
477 return i; // Failed, suppress duplicate error messages
479 if (i.exp.type.isTypeTuple() && i.exp.type.isTypeTuple().arguments.length == 0)
481 Type et = i.exp.type;
482 i.exp = new TupleExp(i.exp.loc, new Expressions());
485 if (i.exp.op == EXP.type)
487 i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars());
490 // Make sure all pointers are constants
491 if (needInterpret && hasNonConstPointers(i.exp))
493 i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
496 Type ti = i.exp.type.toBasetype();
497 if (i.exp.op == EXP.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
499 return new ExpInitializer(i.loc, i.exp);
501 /* Look for case of initializing a static array with a too-short
502 * string literal, such as:
503 * char[5] foo = "abc";
504 * Allow this by doing an explicit cast, which will lengthen the string
507 if (i.exp.op == EXP.string_ && tb.ty == Tsarray)
509 StringExp se = i.exp.isStringExp();
510 Type typeb = se.type.toBasetype();
511 TY tynto = tb.nextOf().ty;
513 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
514 se.numberOfCodeUnits(tynto) < tb.isTypeSArray().dim.toInteger())
516 i.exp = se.castTo(sc, t);
520 /* Lop off terminating 0 of initializer for:
521 * static char s[5] = "hello";
523 if (sc.flags & SCOPE.Cfile &&
524 typeb.ty == Tsarray &&
526 tb.isTypeSArray().dim.toInteger() + 1 == typeb.isTypeSArray().dim.toInteger())
528 i.exp = se.castTo(sc, t);
533 * Initialize an array of unknown size with a string.
534 * Change to static array of known size
536 if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
537 tb.isTypeSArray() && tb.isTypeSArray().isIncomplete())
539 StringExp se = i.exp.isStringExp();
540 auto ts = new TypeSArray(tb.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
541 t = typeSemantic(ts, Loc.initial, sc);
546 // Look for implicit constructor call
547 if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t))
549 StructDeclaration sd = tb.isTypeStruct().sym;
552 // Rewrite as S().ctor(exp)
554 e = new StructLiteralExp(i.loc, sd, null);
555 e = new DotIdExp(i.loc, e, Id.ctor);
556 e = new CallExp(i.loc, e, i.exp);
557 e = e.expressionSemantic(sc);
559 i.exp = e.ctfeInterpret();
561 i.exp = e.optimize(WANTvalue);
563 else if (search_function(sd, Id.call))
565 /* https://issues.dlang.org/show_bug.cgi?id=1547
567 * Look for static opCall
570 * i.exp = typeof(sd).opCall(arguments)
573 Expression e = typeDotIdExp(i.loc, sd.type, Id.call);
574 e = new CallExp(i.loc, e, i.exp);
575 e = e.expressionSemantic(sc);
576 e = resolveProperties(sc, e);
578 i.exp = e.ctfeInterpret();
580 i.exp = e.optimize(WANTvalue);
584 // Look for the case of statically initializing an array with a single member.
585 // Recursively strip static array / enum layers until a compatible element is found,
586 // and return an `ArrayLiteralExp` repeating the initializer, or `null` if no match found
587 // int[2][3] = 7 => [[7, 7], [7, 7], [7, 7]]
588 // int[2] = new Object => null
589 Expression sarrayRepeat(Type tb)
591 auto tsa = tb.isTypeSArray();
595 // printf("i.exp = %s, tsa = %s\n", i.exp.toChars(), tsa.toChars());
596 Expression elem = null;
597 if (i.exp.implicitConvTo(tb.nextOf()))
598 elem = i.exp.implicitCastTo(sc, tb.nextOf());
599 else if (auto ae = sarrayRepeat(tb.nextOf().toBasetype()))
604 auto arrayElements = new Expressions(cast(size_t) tsa.dim.toInteger());
605 foreach (ref e; *arrayElements)
607 return new ArrayLiteralExp(i.exp.loc, tb, elem, arrayElements);
610 if (auto sa = sarrayRepeat(tb))
612 // printf("sa = %s\n", sa.toChars());
617 auto tta = t.isTypeSArray();
618 if (i.exp.implicitConvTo(t))
620 i.exp = i.exp.implicitCastTo(sc, t);
622 else if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
623 tta && (tta.next.ty == Tint8 || tta.next.ty == Tuns8) &&
624 ti.ty == Tsarray && ti.nextOf().ty == Tchar)
626 /* unsigned char bbb[1] = "";
627 * signed char ccc[1] = "";
629 i.exp = i.exp.castTo(sc, t);
633 auto tba = tb.isTypeSArray();
634 // Look for mismatch of compile-time known length to emit
635 // better diagnostic message, as same as AssignExp::semantic.
636 if (tba && i.exp.implicitConvTo(tba.next.arrayOf()) > MATCH.nomatch)
638 uinteger_t dim1 = tba.dim.toInteger();
639 uinteger_t dim2 = dim1;
640 if (auto ale = i.exp.isArrayLiteralExp())
642 dim2 = ale.elements ? ale.elements.length : 0;
644 else if (auto se = i.exp.isSliceExp())
646 if (Type tx = toStaticArrayType(se))
647 dim2 = tx.isTypeSArray().dim.toInteger();
651 i.exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
652 i.exp = ErrorExp.get();
655 Type et = i.exp.type;
656 const errors = global.startGagging();
657 i.exp = i.exp.implicitCastTo(sc, t);
658 if (global.endGagging(errors))
659 currExp.error("cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toChars(), et.toChars(), t.toChars());
663 if (i.exp.op == EXP.error)
668 i.exp = i.exp.ctfeInterpret();
670 i.exp = i.exp.optimize(WANTvalue);
671 //printf("-ExpInitializer::semantic(): "); i.exp.print();
675 Initializer visitC(CInitializer ci)
677 //printf("CInitializer::semantic() (%s) %s\n", t.toChars(), ci.toChars());
678 /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer
682 /* If `{ expression }` return the expression initializer
684 ExpInitializer isBraceExpression()
686 auto dil = ci.initializerList[];
687 return (dil.length == 1 && !dil[0].designatorList)
688 ? dil[0].initializer.isExpInitializer()
692 /********************************
694 bool overlaps(VarDeclaration field, VarDeclaration[] fields, StructInitializer si)
696 foreach (fld; fields)
698 if (field.isOverlappedWith(fld))
700 // look for initializer corresponding with fld
701 foreach (i, ident; si.field[])
703 if (ident == fld.ident && si.value[i])
704 return true; // already an initializer for `field`
711 /* Run semantic on ExpInitializer, see if it represents entire struct ts
713 bool representsStruct(ExpInitializer ei, TypeStruct ts)
717 ei.exp = ei.exp.expressionSemantic(sc);
718 ei.exp = resolveProperties(sc, ei.exp);
721 return ei.exp.implicitConvTo(ts) != MATCH.nomatch; // initializer represents the entire struct
724 /* If { } are omitted from substructs, use recursion to reconstruct where
727 * ts = substruct to initialize
728 * index = index into ci.initializer, updated
729 * Returns: struct initializer for this substruct
731 Initializer subStruct()(TypeStruct ts, ref size_t index)
733 //printf("subStruct(ts: %s, index %d)\n", ts.toChars(), cast(int)index);
735 auto si = new StructInitializer(ci.loc);
736 StructDeclaration sd = ts.sym;
738 if (sd.sizeok != Sizeok.done)
740 index = ci.initializerList.length;
743 const nfields = sd.fields.length;
745 foreach (fieldi; 0 .. nfields)
747 if (index >= ci.initializerList.length)
748 break; // ran out of initializers
749 auto di = ci.initializerList[index];
750 if (di.designatorList && fieldi != 0)
751 break; // back to top level
754 VarDeclaration field;
755 while (1) // skip field if it overlaps with previously seen fields
757 field = sd.fields[fieldi];
759 if (!overlaps(field, sd.fields[], si))
761 if (fieldi == nfields)
764 auto tn = field.type.toBasetype();
765 auto tnsa = tn.isTypeSArray();
766 auto tns = tn.isTypeStruct();
767 auto ix = di.initializer;
768 if (tnsa && ix.isExpInitializer())
770 ExpInitializer ei = ix.isExpInitializer();
771 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
773 si.addInit(field.ident, ei);
777 si.addInit(field.ident, subArray(tnsa, index)); // fwd ref of subArray is why subStruct is a template
779 else if (tns && ix.isExpInitializer())
781 /* Disambiguate between an exp representing the entire
782 * struct, and an exp representing the first field of the struct
784 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
786 si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
789 else // field initializers for struct
790 si.addInit(field.ident, subStruct(tns, index)); // the first field
794 si.addInit(field.ident, ix);
799 //printf("subStruct() returns ai: %s, index: %d\n", si.toChars(), cast(int)index);
803 /* If { } are omitted from subarrays, use recursion to reconstruct where
806 * tsa = subarray to initialize
807 * index = index into ci.initializer, updated
808 * Returns: array initializer for this subarray
810 Initializer subArray(TypeSArray tsa, ref size_t index)
812 //printf("array(tsa: %s, index %d)\n", tsa.toChars(), cast(int)index);
813 if (tsa.isIncomplete())
815 // C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
816 assert(0); // should have been detected by parser
819 auto tnsa = tsa.nextOf().toBasetype().isTypeSArray();
821 auto ai = new ArrayInitializer(ci.loc);
824 foreach (n; 0 .. cast(size_t)tsa.dim.toInteger())
826 if (index >= ci.initializerList.length)
827 break; // ran out of initializers
828 auto di = ci.initializerList[index];
829 if (di.designatorList)
830 break; // back to top level
831 else if (tnsa && di.initializer.isExpInitializer())
833 ExpInitializer ei = di.initializer.isExpInitializer();
834 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
836 ai.addInit(null, ei);
840 ai.addInit(null, subArray(tnsa, index));
844 ai.addInit(null, di.initializer);
848 //printf("array() returns ai: %s, index: %d\n", ai.toChars(), cast(int)index);
852 if (auto ts = t.isTypeStruct())
854 auto si = new StructInitializer(ci.loc);
855 StructDeclaration sd = ts.sym;
856 sd.size(ci.loc); // run semantic() on sd to get fields
857 if (sd.sizeok != Sizeok.done)
861 const nfields = sd.fields.length;
865 for (size_t index = 0; index < ci.initializerList.length; )
867 auto di = ci.initializerList[index];
868 auto dlist = di.designatorList;
871 const length = (*dlist).length;
872 if (length == 0 || !(*dlist)[0].ident)
874 error(ci.loc, "`.identifier` expected for C struct field initializer `%s`", ci.toChars());
879 error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", ci.toChars());
882 auto id = (*dlist)[0].ident;
883 foreach (k, f; sd.fields[]) // linear search for now
888 si.addInit(id, di.initializer);
897 if (fieldi == nfields)
899 VarDeclaration field;
900 while (1) // skip field if it overlaps with previously seen fields
902 field = sd.fields[fieldi];
904 if (!overlaps(field, sd.fields[], si))
906 if (fieldi == nfields)
909 auto tn = field.type.toBasetype();
910 auto tnsa = tn.isTypeSArray();
911 auto tns = tn.isTypeStruct();
912 auto ix = di.initializer;
913 if (tnsa && ix.isExpInitializer())
915 ExpInitializer ei = ix.isExpInitializer();
916 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
918 si.addInit(field.ident, ei);
922 si.addInit(field.ident, subArray(tnsa, index));
924 else if (tns && ix.isExpInitializer())
926 /* Disambiguate between an exp representing the entire
927 * struct, and an exp representing the first field of the struct
929 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
931 si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
934 else // field initializers for struct
935 si.addInit(field.ident, subStruct(tns, index)); // the first field
939 si.addInit(field.ident, di.initializer);
944 return initializerSemantic(si, sc, t, needInterpret);
946 else if (auto ta = t.isTypeSArray())
948 auto tn = t.nextOf().toBasetype(); // element type of array
950 /* If it's an array of integral being initialized by `{ string }`
951 * replace with `string`
955 if (ExpInitializer ei = isBraceExpression())
957 if (ei.exp.isStringExp())
958 return ei.initializerSemantic(sc, t, needInterpret);
962 auto tnsa = tn.isTypeSArray(); // array of array
963 auto tns = tn.isTypeStruct(); // array of struct
965 auto ai = new ArrayInitializer(ci.loc);
967 for (size_t index = 0; index < ci.initializerList.length; )
969 auto di = ci.initializerList[index];
970 if (auto dlist = di.designatorList)
972 const length = (*dlist).length;
973 if (length == 0 || !(*dlist)[0].exp)
975 error(ci.loc, "`[ constant-expression ]` expected for C array element initializer `%s`", ci.toChars());
980 error(ci.loc, "only 1 designator currently allowed for C array element initializer `%s`", ci.toChars());
983 //printf("tn: %s, di.initializer: %s\n", tn.toChars(), di.initializer.toChars());
984 auto ix = di.initializer;
985 if (tnsa && ix.isExpInitializer())
987 // Wrap initializer in [ ]
988 auto ain = new ArrayInitializer(ci.loc);
989 ain.addInit(null, di.initializer);
991 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
994 else if (tns && ix.isExpInitializer())
996 /* Disambiguate between an exp representing the entire
997 * struct, and an exp representing the first field of the struct
999 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
1001 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
1004 else // field initializers for struct
1005 ai.addInit((*dlist)[0].exp, subStruct(tns, index)); // the first field
1009 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
1013 else if (tnsa && di.initializer.isExpInitializer())
1015 ExpInitializer ei = di.initializer.isExpInitializer();
1016 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
1018 ai.addInit(null, ei);
1022 ai.addInit(null, subArray(tnsa, index));
1024 else if (tns && di.initializer.isExpInitializer())
1026 /* Disambiguate between an exp representing the entire
1027 * struct, and an exp representing the first field of the struct
1029 if (representsStruct(di.initializer.isExpInitializer(), tns)) // initializer represents the entire struct
1031 ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
1034 else // field initializers for struct
1035 ai.addInit(null, subStruct(tns, index)); // the first field
1039 ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
1043 return initializerSemantic(ai, sc, tx, needInterpret);
1045 else if (ExpInitializer ei = isBraceExpression())
1046 return visitExp(ei);
1053 final switch (init.kind)
1055 case InitKind.void_: return visitVoid (init.isVoidInitializer());
1056 case InitKind.error: return visitError (init.isErrorInitializer());
1057 case InitKind.struct_: return visitStruct(init.isStructInitializer());
1058 case InitKind.array: return visitArray (init.isArrayInitializer());
1059 case InitKind.exp: return visitExp (init.isExpInitializer());
1060 case InitKind.C_: return visitC (init.isCInitializer());
1064 /***********************
1065 * Translate init to an `Expression` in order to infer the type.
1067 * init = `Initializer` AST node
1070 * an equivalent `ExpInitializer` if successful, or `ErrorInitializer` if it cannot be translated
1072 Initializer inferType(Initializer init, Scope* sc)
1074 Initializer visitVoid(VoidInitializer i)
1076 error(i.loc, "cannot infer type from void initializer");
1077 return new ErrorInitializer();
1080 Initializer visitError(ErrorInitializer i)
1085 Initializer visitStruct(StructInitializer i)
1087 error(i.loc, "cannot infer type from struct initializer");
1088 return new ErrorInitializer();
1091 Initializer visitArray(ArrayInitializer init)
1093 //printf("ArrayInitializer::inferType() %s\n", toChars());
1094 Expressions* keys = null;
1095 Expressions* values;
1096 if (init.isAssociativeArray())
1098 keys = new Expressions(init.value.length);
1099 values = new Expressions(init.value.length);
1100 for (size_t i = 0; i < init.value.length; i++)
1102 Expression e = init.index[i];
1106 Initializer iz = init.value[i];
1109 iz = iz.inferType(sc);
1110 if (iz.isErrorInitializer())
1114 (*values)[i] = iz.isExpInitializer().exp;
1115 assert(!(*values)[i].isErrorExp());
1117 Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
1118 auto ei = new ExpInitializer(init.loc, e);
1119 return ei.inferType(sc);
1123 auto elements = new Expressions(init.value.length);
1125 for (size_t i = 0; i < init.value.length; i++)
1127 assert(!init.index[i]); // already asserted by isAssociativeArray()
1128 Initializer iz = init.value[i];
1131 iz = iz.inferType(sc);
1132 if (iz.isErrorInitializer())
1136 (*elements)[i] = iz.isExpInitializer().exp;
1137 assert(!(*elements)[i].isErrorExp());
1139 Expression e = new ArrayLiteralExp(init.loc, null, elements);
1140 auto ei = new ExpInitializer(init.loc, e);
1141 return ei.inferType(sc);
1146 error(init.loc, "not an associative array initializer");
1150 error(init.loc, "cannot infer type from array initializer");
1152 return new ErrorInitializer();
1155 Initializer visitExp(ExpInitializer init)
1157 //printf("ExpInitializer::inferType() %s\n", init.toChars());
1158 init.exp = init.exp.expressionSemantic(sc);
1160 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1161 if (init.exp.op == EXP.type)
1162 init.exp = resolveAliasThis(sc, init.exp);
1164 init.exp = resolveProperties(sc, init.exp);
1165 if (auto se = init.exp.isScopeExp())
1167 TemplateInstance ti = se.sds.isTemplateInstance();
1168 if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
1169 se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
1171 se.error("cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
1172 return new ErrorInitializer();
1175 // Give error for overloaded function addresses
1177 if (auto f = isFuncAddress(init.exp, &hasOverloads))
1179 if (f.checkForwardRef(init.loc))
1181 return new ErrorInitializer();
1183 if (hasOverloads && !f.isUnique())
1185 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1186 return new ErrorInitializer();
1189 if (auto ae = init.exp.isAddrExp())
1191 if (ae.e1.op == EXP.overloadSet)
1193 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1194 return new ErrorInitializer();
1197 if (init.exp.isErrorExp())
1199 return new ErrorInitializer();
1203 return new ErrorInitializer();
1208 Initializer visitC(CInitializer i)
1210 //printf("CInitializer.inferType()\n");
1211 error(i.loc, "TODO C inferType initializers not supported yet");
1212 return new ErrorInitializer();
1215 final switch (init.kind)
1217 case InitKind.void_: return visitVoid (init.isVoidInitializer());
1218 case InitKind.error: return visitError (init.isErrorInitializer());
1219 case InitKind.struct_: return visitStruct(init.isStructInitializer());
1220 case InitKind.array: return visitArray (init.isArrayInitializer());
1221 case InitKind.exp: return visitExp (init.isExpInitializer());
1222 case InitKind.C_: return visitC (init.isCInitializer());
1226 /***********************
1227 * Translate init to an `Expression`.
1229 * init = `Initializer` AST node
1230 * itype = if not `null`, type to coerce expression to
1231 * isCfile = default initializers are different with C
1233 * `Expression` created, `null` if cannot, `ErrorExp` for other errors
1235 extern (C++) Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false)
1237 //printf("initializerToExpression() isCfile: %d\n", isCfile);
1239 Expression visitVoid(VoidInitializer)
1244 Expression visitError(ErrorInitializer)
1246 return ErrorExp.get();
1249 /***************************************
1250 * This works by transforming a struct initializer into
1251 * a struct literal. In the future, the two should be the
1254 Expression visitStruct(StructInitializer)
1256 // cannot convert to an expression without target 'ad'
1260 /********************************
1261 * If possible, convert array initializer to array literal.
1262 * Otherwise return NULL.
1264 Expression visitArray(ArrayInitializer init)
1266 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
1267 //static int i; if (++i == 2) assert(0);
1268 uint edim; // the length of the resulting array literal
1269 const(uint) amax = 0x80000000;
1270 Type t = null; // type of the array literal being initialized
1273 if (init.type == Type.terror)
1275 return ErrorExp.get();
1277 t = init.type.toBasetype();
1281 t = t.isTypeVector().basetype;
1285 uinteger_t adim = t.isTypeSArray().dim.toInteger();
1288 edim = cast(uint)adim;
1302 /* Calculate the length of the array literal
1304 edim = cast(uint)init.value.length;
1306 foreach (i; 0 .. init.value.length)
1308 if (auto e = init.index[i])
1310 if (e.op == EXP.int64)
1312 const uinteger_t idxval = e.toInteger();
1315 j = cast(size_t)idxval;
1326 auto elements = new Expressions(edim);
1329 foreach (i; 0 .. init.value.length)
1331 if (auto e = init.index[i])
1332 j = cast(size_t)e.toInteger();
1334 if (Initializer iz = init.value[i])
1336 if (Expression ex = iz.initializerToExpression(null, isCfile))
1338 (*elements)[j] = ex;
1348 /* Fill in any missing elements with the default initializer
1350 Expression defaultInit = null; // lazily create it
1351 foreach (ref element; (*elements)[0 .. edim])
1355 if (!init.type) // don't know what type to use
1358 defaultInit = (cast(TypeNext)t).next.defaultInit(Loc.initial, isCfile);
1359 element = defaultInit;
1363 /* Expand any static array initializers that are a single expression
1364 * into an array of them
1365 * e => [e, e, ..., e, e]
1369 Type tn = t.nextOf().toBasetype();
1370 if (tn.ty == Tsarray)
1372 const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger();
1373 Type te = tn.nextOf().toBasetype();
1374 foreach (ref e; *elements)
1376 if (te.equals(e.type))
1378 auto elements2 = new Expressions(dim);
1379 foreach (ref e2; *elements2)
1381 e = new ArrayLiteralExp(e.loc, tn, elements2);
1387 /* If any elements are errors, then the whole thing is an error
1389 foreach (e; (*elements)[0 .. edim])
1391 if (e.op == EXP.error)
1397 Expression e = new ArrayLiteralExp(init.loc, init.type, elements);
1401 Expression visitExp(ExpInitializer i)
1405 //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
1406 Type tb = itype.toBasetype();
1407 Expression e = (i.exp.op == EXP.construct || i.exp.op == EXP.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
1408 if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
1410 TypeSArray tsa = cast(TypeSArray)tb;
1411 size_t d = cast(size_t)tsa.dim.toInteger();
1412 auto elements = new Expressions(d);
1413 for (size_t j = 0; j < d; j++)
1415 auto ae = new ArrayLiteralExp(e.loc, itype, elements);
1422 Expression visitC(CInitializer i)
1424 //printf("CInitializer.initializerToExpression(null, true)\n");
1428 final switch (init.kind)
1430 case InitKind.void_: return visitVoid (init.isVoidInitializer());
1431 case InitKind.error: return visitError (init.isErrorInitializer());
1432 case InitKind.struct_: return visitStruct(init.isStructInitializer());
1433 case InitKind.array: return visitArray (init.isArrayInitializer());
1434 case InitKind.exp: return visitExp (init.isExpInitializer());
1435 case InitKind.C_: return visitC (init.isCInitializer());
1440 /**************************************
1441 * Determine if expression has non-constant pointers, or more precisely,
1442 * a pointer that CTFE cannot handle.
1444 * e = expression to check
1446 * true if it has non-constant pointers
1448 private bool hasNonConstPointers(Expression e)
1450 static bool checkArray(Expressions* elems)
1454 if (e && hasNonConstPointers(e))
1460 if (e.type.ty == Terror)
1462 if (e.op == EXP.null_)
1464 if (auto se = e.isStructLiteralExp())
1466 return checkArray(se.elements);
1468 if (auto ae = e.isArrayLiteralExp())
1470 if (!ae.type.nextOf().hasPointers())
1472 return checkArray(ae.elements);
1474 if (auto ae = e.isAssocArrayLiteralExp())
1476 if (ae.type.nextOf().hasPointers() && checkArray(ae.values))
1478 if (ae.type.isTypeAArray().index.hasPointers())
1479 return checkArray(ae.keys);
1482 if (auto ae = e.isAddrExp())
1484 if (ae.type.nextOf().isImmutable() || ae.type.nextOf().isConst())
1488 if (auto se = ae.e1.isStructLiteralExp())
1490 if (!(se.stageflags & stageSearchPointers))
1492 const old = se.stageflags;
1493 se.stageflags |= stageSearchPointers;
1494 bool ret = checkArray(se.elements);
1495 se.stageflags = old;
1505 if (e.type.ty == Tpointer && !e.type.isPtrToFunction())
1507 if (e.op == EXP.symbolOffset) // address of a global is OK
1509 if (e.op == EXP.int64) // cast(void *)int is OK
1511 if (e.op == EXP.string_) // "abc".ptr is OK