d: Merge upstream dmd ff57fec515, druntime ff57fec515, phobos 17bafda79.
[official-gcc.git] / gcc / d / dmd / initsem.d
blob76c2d8916b0bd34c56fd592082e386deb1cc3301
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.dinterpret;
24 import dmd.dscope;
25 import dmd.dstruct;
26 import dmd.dsymbol;
27 import dmd.dsymbolsem;
28 import dmd.dtemplate;
29 import dmd.errors;
30 import dmd.expression;
31 import dmd.expressionsem;
32 import dmd.func;
33 import dmd.globals;
34 import dmd.hdrgen;
35 import dmd.id;
36 import dmd.identifier;
37 import dmd.importc;
38 import dmd.init;
39 import dmd.location;
40 import dmd.mtype;
41 import dmd.opover;
42 import dmd.optimize;
43 import dmd.statement;
44 import dmd.target;
45 import dmd.tokens;
46 import dmd.typesem;
48 /********************************
49 * If possible, convert array initializer to associative array initializer.
51 * Params:
52 * ai = array initializer to be converted
54 * Returns:
55 * The converted associative array initializer or ErrorExp if `ai`
56 * is not an associative array initializer.
58 Expression toAssocArrayLiteral(ArrayInitializer ai)
60 //printf("ArrayInitializer::toAssocArrayInitializer(%s)\n", ai.toChars());
61 //static int i; if (++i == 2) assert(0);
62 const dim = ai.value.length;
63 if (!dim)
65 error(ai.loc, "invalid associative array initializer `%s`, use `null` instead",
66 toChars(ai));
67 return ErrorExp.get();
69 auto no(const char* format, Initializer i)
71 error(i.loc, format, toChars(i));
72 return ErrorExp.get();
74 Expression e;
75 auto keys = new Expressions(dim);
76 auto values = new Expressions(dim);
77 for (size_t i = 0; i < dim; i++)
79 Initializer iz = ai.value[i];
80 assert(iz);
81 e = iz.initializerToExpression();
82 if (!e)
83 return no("invalid value `%s` in initializer", iz);
84 (*values)[i] = e;
85 e = ai.index[i];
86 if (!e)
87 return no("missing key for value `%s` in initializer", iz);
88 (*keys)[i] = e;
90 e = new AssocArrayLiteralExp(ai.loc, keys, values);
91 return e;
94 /******************************************
95 * Perform semantic analysis on init.
96 * Params:
97 * init = Initializer AST node
98 * sc = context
99 * tx = type that the initializer needs to become. If tx is an incomplete
100 * type and the initializer completes it, it is updated to be the
101 * complete type. ImportC has incomplete types
102 * needInterpret = if CTFE needs to be run on this,
103 * such as if it is the initializer for a const declaration
104 * Returns:
105 * `Initializer` with completed semantic analysis, `ErrorInitializer` if errors
106 * were encountered
108 extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
110 //printf("initializerSemantic() tx: %p %s\n", tx, tx.toChars());
111 Type t = tx;
113 static Initializer err()
115 return new ErrorInitializer();
118 Initializer visitVoid(VoidInitializer i)
120 i.type = t;
121 return i;
124 Initializer visitDefault(DefaultInitializer i)
126 i.type = t;
127 return i;
130 Initializer visitError(ErrorInitializer i)
132 return i;
135 Initializer visitStruct(StructInitializer i)
137 //printf("StructInitializer::semantic(t = %s) %s\n", t.toChars(), i.toChars());
138 /* This works by replacing the StructInitializer with an ExpInitializer.
140 t = t.toBasetype();
141 if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct)
142 t = t.nextOf().toBasetype();
143 if (auto ts = t.isTypeStruct())
145 StructDeclaration sd = ts.sym;
146 // check if the sd has a regular ctor (user defined non-copy ctor)
147 // that is not disabled.
148 if (sd.hasRegularCtor(true))
150 error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars());
151 return err();
153 sd.size(i.loc);
154 if (sd.sizeok != Sizeok.done)
155 return err();
157 Expression getExp(size_t j, Type fieldType)
159 // Convert initializer to Expression `ex`
160 auto tm = fieldType.addMod(t.mod);
161 auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret);
162 auto ex = iz.initializerToExpression(null, (sc.flags & SCOPE.Cfile) != 0);
163 if (ex.op != EXP.error)
164 i.value[j] = iz;
165 return ex;
167 auto elements = resolveStructLiteralNamedArgs(sd, t, sc, i.loc, i.field[], &getExp, (size_t j) => i.value[j].loc);
168 if (!elements)
169 return err();
171 // Make a StructLiteralExp out of elements[]
172 auto sle = new StructLiteralExp(i.loc, sd, elements, t);
173 if (!sd.fill(i.loc, *elements, false))
174 return err();
175 sle.type = t;
176 auto ie = new ExpInitializer(i.loc, sle);
177 return ie.initializerSemantic(sc, t, needInterpret);
179 else if ((t.ty == Tdelegate || t.isPtrToFunction()) && i.value.length == 0)
181 const tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_;
182 /* Rewrite as empty delegate literal { }
184 Type tf = new TypeFunction(ParameterList(), null, LINK.d);
185 auto fd = new FuncLiteralDeclaration(i.loc, Loc.initial, tf, tok, null);
186 fd.fbody = new CompoundStatement(i.loc, new Statements());
187 fd.endloc = i.loc;
188 Expression e = new FuncExp(i.loc, fd);
189 auto ie = new ExpInitializer(i.loc, e);
190 return ie.initializerSemantic(sc, t, needInterpret);
192 if (t.ty != Terror)
193 error(i.loc, "a struct is not a valid initializer for a `%s`", t.toChars());
194 return err();
197 Initializer visitArray(ArrayInitializer i)
199 uint length;
200 const(uint) amax = 0x80000000;
201 bool errors = false;
202 //printf("ArrayInitializer::semantic(%s), ai: %s %p\n", t.toChars(), i.toChars(), i);
203 if (i.sem) // if semantic() already run
205 return i;
207 i.sem = true;
208 t = t.toBasetype();
209 switch (t.ty)
211 case Tsarray:
212 case Tarray:
213 break;
214 case Tvector:
215 t = t.isTypeVector().basetype;
216 break;
217 case Taarray:
218 case Tstruct: // consider implicit constructor call
220 Expression e;
221 // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int])
222 if (t.ty == Taarray || i.isAssociativeArray())
223 e = i.toAssocArrayLiteral();
224 else
225 e = i.initializerToExpression();
226 // Bugzilla 13987
227 if (!e)
229 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
230 return err();
232 auto ei = new ExpInitializer(e.loc, e);
233 return ei.initializerSemantic(sc, t, needInterpret);
235 case Tpointer:
236 if (t.nextOf().ty != Tfunction)
237 break;
238 goto default;
239 default:
240 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
241 return err();
243 i.type = t;
244 length = 0;
245 for (size_t j = 0; j < i.index.length; j++)
247 Expression idx = i.index[j];
248 if (idx)
250 sc = sc.startCTFE();
251 idx = idx.expressionSemantic(sc);
252 sc = sc.endCTFE();
253 idx = idx.ctfeInterpret();
254 i.index[j] = idx;
255 const uinteger_t idxvalue = idx.toInteger();
256 if (idxvalue >= amax)
258 error(i.loc, "array index %llu overflow", idxvalue);
259 errors = true;
261 length = cast(uint)idxvalue;
262 if (idx.op == EXP.error)
263 errors = true;
265 Initializer val = i.value[j];
266 ExpInitializer ei = val.isExpInitializer();
267 if (ei && !idx)
268 ei.expandTuples = true;
269 auto tn = t.nextOf();
270 val = val.initializerSemantic(sc, tn, needInterpret);
271 if (val.isErrorInitializer())
272 errors = true;
273 ei = val.isExpInitializer();
274 // found a tuple, expand it
275 if (ei && ei.exp.op == EXP.tuple)
277 TupleExp te = ei.exp.isTupleExp();
278 i.index.remove(j);
279 i.value.remove(j);
280 for (size_t k = 0; k < te.exps.length; ++k)
282 Expression e = (*te.exps)[k];
283 i.index.insert(j + k, cast(Expression)null);
284 i.value.insert(j + k, new ExpInitializer(e.loc, e));
286 j--;
287 continue;
289 else
291 i.value[j] = val;
293 length++;
294 if (length == 0)
296 error(i.loc, "array dimension overflow");
297 return err();
299 if (length > i.dim)
300 i.dim = length;
302 if (auto tsa = t.isTypeSArray())
304 if (sc.flags & SCOPE.Cfile && tsa.isIncomplete())
306 // Change to array of known length
307 auto tn = tsa.next.toBasetype();
308 tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, i.dim, Type.tsize_t));
309 tx = tsa; // rewrite caller's type
310 i.type = tsa; // remember for later passes
312 else
314 uinteger_t edim = tsa.dim.toInteger();
315 if (i.dim > edim)
317 error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
318 return err();
322 if (errors)
323 return err();
325 const sz = t.nextOf().size();
326 if (sz == SIZE_INVALID)
327 return err();
328 bool overflow;
329 const max = mulu(i.dim, sz, overflow);
330 if (overflow || max >= amax)
332 error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz));
333 return err();
335 //printf("returns ai: %s\n", i.toChars());
336 return i;
339 Initializer visitExp(ExpInitializer i)
341 //printf("ExpInitializer::semantic(%s), type = %s\n", i.exp.toChars(), t.toChars());
342 if (needInterpret)
343 sc = sc.startCTFE();
344 i.exp = i.exp.expressionSemantic(sc);
345 i.exp = resolveProperties(sc, i.exp);
346 if (needInterpret)
347 sc = sc.endCTFE();
348 if (i.exp.op == EXP.error)
349 return err();
350 uint olderrors = global.errors;
352 /* ImportC: convert arrays to pointers, functions to pointers to functions
354 Type tb = t.toBasetype();
355 if (tb.isTypePointer())
356 i.exp = i.exp.arrayFuncConv(sc);
358 /* Save the expression before ctfe
359 * Otherwise the error message would contain for example "&[0][0]" instead of "new int"
360 * Regression: https://issues.dlang.org/show_bug.cgi?id=21687
362 Expression currExp = i.exp;
363 if (needInterpret)
365 // If the result will be implicitly cast, move the cast into CTFE
366 // to avoid premature truncation of polysemous types.
367 // eg real [] x = [1.1, 2.2]; should use real precision.
368 if (i.exp.implicitConvTo(t) && !(sc.flags & SCOPE.Cfile))
370 i.exp = i.exp.implicitCastTo(sc, t);
372 if (!global.gag && olderrors != global.errors)
374 return i;
376 if (sc.flags & SCOPE.Cfile)
378 /* the interpreter turns (char*)"string" into &"string"[0] which then
379 * it cannot interpret. Resolve that case by doing optimize() first
381 i.exp = i.exp.optimize(WANTvalue);
382 if (i.exp.isSymOffExp())
384 /* `static variable cannot be read at compile time`
385 * https://issues.dlang.org/show_bug.cgi?id=22513
386 * Maybe this would be better addressed in ctfeInterpret()?
388 needInterpret = NeedInterpret.INITnointerpret;
391 if (needInterpret)
392 i.exp = i.exp.ctfeInterpret();
393 if (i.exp.op == EXP.voidExpression)
394 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
396 else
398 i.exp = i.exp.optimize(WANTvalue);
401 if (!global.gag && olderrors != global.errors)
403 return i; // Failed, suppress duplicate error messages
405 if (i.exp.type.isTypeTuple() && i.exp.type.isTypeTuple().arguments.length == 0)
407 Type et = i.exp.type;
408 i.exp = new TupleExp(i.exp.loc, new Expressions());
409 i.exp.type = et;
411 if (i.exp.op == EXP.type)
413 error(i.exp.loc, "initializer must be an expression, not `%s`", i.exp.toChars());
414 return err();
416 // Make sure all pointers are constants
417 if (needInterpret && hasNonConstPointers(i.exp))
419 error(i.exp.loc, "cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
420 return err();
422 Type ti = i.exp.type.toBasetype();
423 if (i.exp.op == EXP.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
425 return new ExpInitializer(i.loc, i.exp);
427 /* Look for case of initializing a static array with a too-short
428 * string literal, such as:
429 * char[5] foo = "abc";
430 * Allow this by doing an explicit cast, which will lengthen the string
431 * literal.
433 if (i.exp.op == EXP.string_ && tb.ty == Tsarray)
435 StringExp se = i.exp.isStringExp();
436 Type typeb = se.type.toBasetype();
437 TY tynto = tb.nextOf().ty;
438 if (!se.committed &&
439 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
440 se.numberOfCodeUnits(tynto) < tb.isTypeSArray().dim.toInteger())
442 i.exp = se.castTo(sc, t);
443 goto L1;
446 /* Lop off terminating 0 of initializer for:
447 * static char s[5] = "hello";
449 if (sc.flags & SCOPE.Cfile &&
450 typeb.ty == Tsarray &&
451 tynto.isSomeChar &&
452 tb.isTypeSArray().dim.toInteger() + 1 == typeb.isTypeSArray().dim.toInteger())
454 i.exp = se.castTo(sc, t);
455 goto L1;
458 /* C11 6.7.9-14..15
459 * Initialize an array of unknown size with a string.
460 * Change to static array of known size
462 if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
463 tb.isTypeSArray() && tb.isTypeSArray().isIncomplete())
465 StringExp se = i.exp.isStringExp();
466 auto ts = new TypeSArray(tb.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
467 t = typeSemantic(ts, Loc.initial, sc);
468 i.exp.type = t;
469 tx = t;
472 // Look for implicit constructor call
473 if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t))
475 StructDeclaration sd = tb.isTypeStruct().sym;
476 if (sd.ctor)
478 // Rewrite as S().ctor(exp)
479 Expression e;
480 e = new StructLiteralExp(i.loc, sd, null);
481 e = new DotIdExp(i.loc, e, Id.ctor);
482 e = new CallExp(i.loc, e, i.exp);
483 e = e.expressionSemantic(sc);
484 if (needInterpret)
485 i.exp = e.ctfeInterpret();
486 else
487 i.exp = e.optimize(WANTvalue);
489 else if (search_function(sd, Id.call))
491 /* https://issues.dlang.org/show_bug.cgi?id=1547
493 * Look for static opCall
495 * Rewrite as:
496 * i.exp = typeof(sd).opCall(arguments)
499 Expression e = typeDotIdExp(i.loc, sd.type, Id.call);
500 e = new CallExp(i.loc, e, i.exp);
501 e = e.expressionSemantic(sc);
502 e = resolveProperties(sc, e);
503 if (needInterpret)
504 i.exp = e.ctfeInterpret();
505 else
506 i.exp = e.optimize(WANTvalue);
510 // Look for the case of statically initializing an array with a single member.
511 // Recursively strip static array / enum layers until a compatible element is found,
512 // and return an `ArrayLiteralExp` repeating the initializer, or `null` if no match found
513 // int[2][3] = 7 => [[7, 7], [7, 7], [7, 7]]
514 // int[2] = new Object => null
515 Expression sarrayRepeat(Type tb)
517 auto tsa = tb.isTypeSArray();
518 if (!tsa)
519 return null;
521 // printf("i.exp = %s, tsa = %s\n", i.exp.toChars(), tsa.toChars());
522 Expression elem = null;
523 if (i.exp.implicitConvTo(tb.nextOf()))
524 elem = i.exp.implicitCastTo(sc, tb.nextOf());
525 else if (auto ae = sarrayRepeat(tb.nextOf().toBasetype()))
526 elem = ae;
527 else
528 return null;
530 auto arrayElements = new Expressions(cast(size_t) tsa.dim.toInteger());
531 foreach (ref e; *arrayElements)
532 e = elem;
533 return new ArrayLiteralExp(i.exp.loc, tb, elem, arrayElements);
536 if (auto sa = sarrayRepeat(tb))
538 // printf("sa = %s\n", sa.toChars());
539 i.exp = sa;
543 auto tta = t.isTypeSArray();
544 if (i.exp.implicitConvTo(t))
546 i.exp = i.exp.implicitCastTo(sc, t);
548 else if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
549 tta && (tta.next.ty == Tint8 || tta.next.ty == Tuns8) &&
550 ti.ty == Tsarray && ti.nextOf().ty == Tchar)
552 /* unsigned char bbb[1] = "";
553 * signed char ccc[1] = "";
555 i.exp = i.exp.castTo(sc, t);
557 else
559 auto tba = tb.isTypeSArray();
560 // Look for mismatch of compile-time known length to emit
561 // better diagnostic message, as same as AssignExp::semantic.
562 if (tba && i.exp.implicitConvTo(tba.next.arrayOf()) > MATCH.nomatch)
564 uinteger_t dim1 = tba.dim.toInteger();
565 uinteger_t dim2 = dim1;
566 if (auto ale = i.exp.isArrayLiteralExp())
568 dim2 = ale.elements ? ale.elements.length : 0;
570 else if (auto se = i.exp.isSliceExp())
572 if (Type tx = toStaticArrayType(se))
573 dim2 = tx.isTypeSArray().dim.toInteger();
575 if (dim1 != dim2)
577 error(i.exp.loc, "mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
578 i.exp = ErrorExp.get();
581 Type et = i.exp.type;
582 const errors = global.startGagging();
583 i.exp = i.exp.implicitCastTo(sc, t);
584 if (global.endGagging(errors))
585 error(currExp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toChars(), et.toChars(), t.toChars());
589 if (i.exp.op == EXP.error)
591 return i;
593 if (needInterpret)
594 i.exp = i.exp.ctfeInterpret();
595 else
596 i.exp = i.exp.optimize(WANTvalue);
597 //printf("-ExpInitializer::semantic(): "); i.exp.print();
598 return i;
601 Initializer visitC(CInitializer ci)
603 //printf("CInitializer::semantic() tx: %s t: %s ci: %s\n", (tx ? tx.toChars() : "".ptr), t.toChars(), ci.toChars());
604 /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer
606 t = t.toBasetype();
608 if (auto tv = t.isTypeVector())
609 t = tv.basetype;
611 /* If `{ expression }` return the expression initializer
613 ExpInitializer isBraceExpression()
615 auto dil = ci.initializerList[];
616 return (dil.length == 1 && !dil[0].designatorList)
617 ? dil[0].initializer.isExpInitializer()
618 : null;
621 /********************************
623 bool overlaps(VarDeclaration field, VarDeclaration[] fields, StructInitializer si)
625 foreach (fld; fields)
627 if (field.isOverlappedWith(fld))
629 // look for initializer corresponding with fld
630 foreach (i, ident; si.field[])
632 if (ident == fld.ident && si.value[i])
633 return true; // already an initializer for `field`
637 return false;
640 /* Run semantic on ExpInitializer, see if it represents entire struct ts
642 bool representsStruct(ExpInitializer ei, TypeStruct ts)
644 if (needInterpret)
645 sc = sc.startCTFE();
646 ei.exp = ei.exp.expressionSemantic(sc);
647 ei.exp = resolveProperties(sc, ei.exp);
648 if (needInterpret)
649 sc = sc.endCTFE();
650 return ei.exp.implicitConvTo(ts) != MATCH.nomatch; // initializer represents the entire struct
653 /* If { } are omitted from substructs, use recursion to reconstruct where
654 * brackets go
655 * Params:
656 * ts = substruct to initialize
657 * index = index into ci.initializer, updated
658 * Returns: struct initializer for this substruct
660 Initializer subStruct()(TypeStruct ts, ref size_t index)
662 //printf("subStruct(ts: %s, index %d)\n", ts.toChars(), cast(int)index);
664 auto si = new StructInitializer(ci.loc);
665 StructDeclaration sd = ts.sym;
666 sd.size(ci.loc);
667 if (sd.sizeok != Sizeok.done)
669 index = ci.initializerList.length;
670 return err();
672 const nfields = sd.fields.length;
674 foreach (fieldi; 0 .. nfields)
676 if (index >= ci.initializerList.length)
677 break; // ran out of initializers
678 auto di = ci.initializerList[index];
679 if (di.designatorList && fieldi != 0)
680 break; // back to top level
681 else
683 VarDeclaration field;
684 while (1) // skip field if it overlaps with previously seen fields
686 field = sd.fields[fieldi];
687 ++fieldi;
688 if (!overlaps(field, sd.fields[], si))
689 break;
690 if (fieldi == nfields)
691 break;
693 auto tn = field.type.toBasetype();
694 auto tnsa = tn.isTypeSArray();
695 auto tns = tn.isTypeStruct();
696 auto ix = di.initializer;
697 if (tnsa && ix.isExpInitializer())
699 ExpInitializer ei = ix.isExpInitializer();
700 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
702 si.addInit(field.ident, ei);
703 ++index;
705 else
706 si.addInit(field.ident, subArray(tnsa, index)); // fwd ref of subArray is why subStruct is a template
708 else if (tns && ix.isExpInitializer())
710 /* Disambiguate between an exp representing the entire
711 * struct, and an exp representing the first field of the struct
713 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
715 si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
716 ++index;
718 else // field initializers for struct
719 si.addInit(field.ident, subStruct(tns, index)); // the first field
721 else
723 si.addInit(field.ident, ix);
724 ++index;
728 //printf("subStruct() returns ai: %s, index: %d\n", si.toChars(), cast(int)index);
729 return si;
732 /* If { } are omitted from subarrays, use recursion to reconstruct where
733 * brackets go
734 * Params:
735 * tsa = subarray to initialize
736 * index = index into ci.initializer, updated
737 * Returns: array initializer for this subarray
739 Initializer subArray(TypeSArray tsa, ref size_t index)
741 //printf("array(tsa: %s, index %d)\n", tsa.toChars(), cast(int)index);
742 if (tsa.isIncomplete())
744 // C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
745 assert(0); // should have been detected by parser
748 auto tnsa = tsa.nextOf().toBasetype().isTypeSArray();
750 auto ai = new ArrayInitializer(ci.loc);
751 ai.isCarray = true;
753 foreach (n; 0 .. cast(size_t)tsa.dim.toInteger())
755 if (index >= ci.initializerList.length)
756 break; // ran out of initializers
757 auto di = ci.initializerList[index];
758 if (di.designatorList)
759 break; // back to top level
760 else if (tnsa && di.initializer.isExpInitializer())
762 ExpInitializer ei = di.initializer.isExpInitializer();
763 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
765 ai.addInit(null, ei);
766 ++index;
768 else
769 ai.addInit(null, subArray(tnsa, index));
771 else
773 ai.addInit(null, di.initializer);
774 ++index;
777 //printf("array() returns ai: %s, index: %d\n", ai.toChars(), cast(int)index);
778 return ai;
781 if (auto ts = t.isTypeStruct())
783 auto si = new StructInitializer(ci.loc);
784 StructDeclaration sd = ts.sym;
785 sd.size(ci.loc); // run semantic() on sd to get fields
786 if (sd.sizeok != Sizeok.done)
788 return err();
790 const nfields = sd.fields.length;
791 size_t fieldi = 0;
793 Loop1:
794 for (size_t index = 0; index < ci.initializerList.length; )
796 CInitializer cprev;
798 DesigInit di = ci.initializerList[index];
799 Designators* dlist = di.designatorList;
800 if (dlist)
802 const length = (*dlist).length;
803 if (length == 0 || !(*dlist)[0].ident)
805 error(ci.loc, "`.identifier` expected for C struct field initializer `%s`", toChars(ci));
806 return err();
808 if (length > 1)
810 error(ci.loc, "only 1 designator currently allowed for C struct field initializer `%s`", toChars(ci));
811 return err();
813 auto id = (*dlist)[0].ident;
814 foreach (k, f; sd.fields[]) // linear search for now
816 if (f.ident == id)
818 fieldi = k;
819 si.addInit(id, di.initializer);
820 ++fieldi;
821 ++index;
822 continue Loop1;
825 if (cprev)
827 /* The peeling didn't work, so unpeel it
829 ci = cprev;
830 di = ci.initializerList[index];
831 goto L2;
833 error(ci.loc, "`.%s` is not a field of `%s`\n", id.toChars(), sd.toChars());
834 return err();
836 else
838 if (fieldi == nfields)
839 break;
840 if (index == 0 && ci.initializerList.length == 1 && di.initializer.isCInitializer())
842 /* Try peeling off this set of { } and see if it works
844 cprev = ci;
845 ci = di.initializer.isCInitializer();
846 goto L1;
850 VarDeclaration field;
851 while (1) // skip field if it overlaps with previously seen fields
853 field = sd.fields[fieldi];
854 ++fieldi;
855 if (!overlaps(field, sd.fields[], si))
856 break;
857 if (fieldi == nfields)
858 break;
860 auto tn = field.type.toBasetype();
861 auto tnsa = tn.isTypeSArray();
862 auto tns = tn.isTypeStruct();
863 auto ix = di.initializer;
864 if (tnsa && ix.isExpInitializer())
866 ExpInitializer ei = ix.isExpInitializer();
867 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
869 si.addInit(field.ident, ei);
870 ++index;
872 else
873 si.addInit(field.ident, subArray(tnsa, index));
875 else if (tns && ix.isExpInitializer())
877 /* Disambiguate between an exp representing the entire
878 * struct, and an exp representing the first field of the struct
880 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
882 si.addInit(field.ident, initializerSemantic(ix, sc, tn, needInterpret));
883 ++index;
885 else // field initializers for struct
886 si.addInit(field.ident, subStruct(tns, index)); // the first field
888 else
890 si.addInit(field.ident, di.initializer);
891 ++index;
895 return initializerSemantic(si, sc, t, needInterpret);
897 else if (auto ta = t.isTypeSArray())
899 auto tn = t.nextOf().toBasetype(); // element type of array
901 /* If it's an array of integral being initialized by `{ string }`
902 * replace with `string`
904 if (tn.isintegral())
906 if (ExpInitializer ei = isBraceExpression())
908 if (ei.exp.isStringExp())
909 return ei.initializerSemantic(sc, t, needInterpret);
913 auto tnsa = tn.isTypeSArray(); // array of array
914 auto tns = tn.isTypeStruct(); // array of struct
916 auto ai = new ArrayInitializer(ci.loc);
917 ai.isCarray = true;
918 for (size_t index = 0; index < ci.initializerList.length; )
920 auto di = ci.initializerList[index];
921 if (auto dlist = di.designatorList)
923 const length = (*dlist).length;
924 if (length == 0 || !(*dlist)[0].exp)
926 error(ci.loc, "`[ constant-expression ]` expected for C array element initializer `%s`", toChars(ci));
927 return err();
929 if (length > 1)
931 error(ci.loc, "only 1 designator currently allowed for C array element initializer `%s`", toChars(ci));
932 return err();
934 //printf("tn: %s, di.initializer: %s\n", tn.toChars(), di.initializer.toChars());
935 auto ix = di.initializer;
936 if (tnsa && ix.isExpInitializer())
938 // Wrap initializer in [ ]
939 auto ain = new ArrayInitializer(ci.loc);
940 ain.addInit(null, di.initializer);
941 ix = ain;
942 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
943 ++index;
945 else if (tns && ix.isExpInitializer())
947 /* Disambiguate between an exp representing the entire
948 * struct, and an exp representing the first field of the struct
950 if (representsStruct(ix.isExpInitializer(), tns)) // initializer represents the entire struct
952 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
953 ++index;
955 else // field initializers for struct
956 ai.addInit((*dlist)[0].exp, subStruct(tns, index)); // the first field
958 else
960 ai.addInit((*dlist)[0].exp, initializerSemantic(ix, sc, tn, needInterpret));
961 ++index;
964 else if (tnsa && di.initializer.isExpInitializer())
966 ExpInitializer ei = di.initializer.isExpInitializer();
967 if (ei.exp.isStringExp() && tnsa.nextOf().isintegral())
969 ai.addInit(null, ei);
970 ++index;
972 else
973 ai.addInit(null, subArray(tnsa, index));
975 else if (tns && di.initializer.isExpInitializer())
977 /* Disambiguate between an exp representing the entire
978 * struct, and an exp representing the first field of the struct
980 if (representsStruct(di.initializer.isExpInitializer(), tns)) // initializer represents the entire struct
982 ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
983 ++index;
985 else // field initializers for struct
986 ai.addInit(null, subStruct(tns, index)); // the first field
988 else
990 ai.addInit(null, initializerSemantic(di.initializer, sc, tn, needInterpret));
991 ++index;
994 return initializerSemantic(ai, sc, tx, needInterpret);
996 else if (ExpInitializer ei = isBraceExpression())
998 return visitExp(ei);
1000 else
1002 error(ci.loc, "unrecognized C initializer `%s`", toChars(ci));
1003 return err();
1007 mixin VisitInitializer!Initializer visit;
1008 auto result = visit.VisitInitializer(init);
1009 return (result !is null) ? result : new ErrorInitializer();
1012 /***********************
1013 * Translate init to an `Expression` in order to infer the type.
1014 * Params:
1015 * init = `Initializer` AST node
1016 * sc = context
1017 * Returns:
1018 * an equivalent `ExpInitializer` if successful, or `ErrorInitializer` if it cannot be translated
1020 Initializer inferType(Initializer init, Scope* sc)
1022 Initializer visitVoid(VoidInitializer i)
1024 error(i.loc, "cannot infer type from void initializer");
1025 return new ErrorInitializer();
1028 Initializer visitDefault(DefaultInitializer i)
1030 error(i.loc, "cannot infer type from default initializer");
1031 return new ErrorInitializer();
1034 Initializer visitError(ErrorInitializer i)
1036 return i;
1039 Initializer visitStruct(StructInitializer i)
1041 error(i.loc, "cannot infer type from struct initializer");
1042 return new ErrorInitializer();
1045 Initializer visitArray(ArrayInitializer init)
1047 //printf("ArrayInitializer::inferType() %s\n", toChars());
1048 Expressions* keys = null;
1049 Expressions* values;
1050 if (init.isAssociativeArray())
1052 keys = new Expressions(init.value.length);
1053 values = new Expressions(init.value.length);
1054 for (size_t i = 0; i < init.value.length; i++)
1056 Expression e = init.index[i];
1057 if (!e)
1058 goto Lno;
1059 (*keys)[i] = e;
1060 Initializer iz = init.value[i];
1061 if (!iz)
1062 goto Lno;
1063 iz = iz.inferType(sc);
1064 if (iz.isErrorInitializer())
1066 return iz;
1068 (*values)[i] = iz.isExpInitializer().exp;
1069 assert(!(*values)[i].isErrorExp());
1071 Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
1072 auto ei = new ExpInitializer(init.loc, e);
1073 return ei.inferType(sc);
1075 else
1077 auto elements = new Expressions(init.value.length);
1078 elements.zero();
1079 for (size_t i = 0; i < init.value.length; i++)
1081 assert(!init.index[i]); // already asserted by isAssociativeArray()
1082 Initializer iz = init.value[i];
1083 if (!iz)
1084 goto Lno;
1085 iz = iz.inferType(sc);
1086 if (iz.isErrorInitializer())
1088 return iz;
1090 (*elements)[i] = iz.isExpInitializer().exp;
1091 assert(!(*elements)[i].isErrorExp());
1093 Expression e = new ArrayLiteralExp(init.loc, null, elements);
1094 auto ei = new ExpInitializer(init.loc, e);
1095 return ei.inferType(sc);
1097 Lno:
1098 if (keys)
1100 error(init.loc, "not an associative array initializer");
1102 else
1104 error(init.loc, "cannot infer type from array initializer");
1106 return new ErrorInitializer();
1109 Initializer visitExp(ExpInitializer init)
1111 //printf("ExpInitializer::inferType() %s\n", init.toChars());
1112 init.exp = init.exp.expressionSemantic(sc);
1114 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1115 if (init.exp.op == EXP.type)
1116 init.exp = resolveAliasThis(sc, init.exp);
1118 init.exp = resolveProperties(sc, init.exp);
1119 if (auto se = init.exp.isScopeExp())
1121 TemplateInstance ti = se.sds.isTemplateInstance();
1122 if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
1123 error(se.loc, "cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
1124 else
1125 error(se.loc, "cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
1126 return new ErrorInitializer();
1129 // Give error for overloaded function addresses
1130 bool hasOverloads;
1131 if (auto f = isFuncAddress(init.exp, &hasOverloads))
1133 if (f.checkForwardRef(init.loc))
1135 return new ErrorInitializer();
1137 if (hasOverloads && !f.isUnique())
1139 error(init.exp.loc, "cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1140 return new ErrorInitializer();
1143 if (auto ae = init.exp.isAddrExp())
1145 if (ae.e1.op == EXP.overloadSet)
1147 error(init.exp.loc, "cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1148 return new ErrorInitializer();
1151 if (init.exp.isErrorExp())
1153 return new ErrorInitializer();
1155 if (!init.exp.type)
1157 return new ErrorInitializer();
1159 return init;
1162 Initializer visitC(CInitializer i)
1164 //printf("CInitializer.inferType()\n");
1165 error(i.loc, "TODO C inferType initializers not supported yet");
1166 return new ErrorInitializer();
1169 mixin VisitInitializer!Initializer visit;
1170 auto result = visit.VisitInitializer(init);
1171 return (result !is null) ? result : new ErrorInitializer();
1174 /***********************
1175 * Translate init to an `Expression`.
1176 * Params:
1177 * init = `Initializer` AST node
1178 * itype = if not `null`, type to coerce expression to
1179 * isCfile = default initializers are different with C
1180 * Returns:
1181 * `Expression` created, `null` if cannot, `ErrorExp` for other errors
1183 extern (C++) Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false)
1185 //printf("initializerToExpression() isCfile: %d\n", isCfile);
1187 Expression visitVoid(VoidInitializer)
1189 return null;
1192 Expression visitDefault(DefaultInitializer di)
1194 return di.type ? di.type.defaultInit(Loc.initial, isCfile) : null;
1197 Expression visitError(ErrorInitializer)
1199 return ErrorExp.get();
1202 /***************************************
1203 * This works by transforming a struct initializer into
1204 * a struct literal. In the future, the two should be the
1205 * same thing.
1207 Expression visitStruct(StructInitializer)
1209 // cannot convert to an expression without target 'ad'
1210 return null;
1213 /********************************
1214 * If possible, convert array initializer to array literal.
1215 * Otherwise return NULL.
1217 Expression visitArray(ArrayInitializer init)
1219 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
1220 //static int i; if (++i == 2) assert(0);
1221 uint edim; // the length of the resulting array literal
1222 const(uint) amax = 0x80000000;
1223 Type t = null; // type of the array literal being initialized
1224 if (init.type)
1226 if (init.type == Type.terror)
1228 return ErrorExp.get();
1230 t = init.type.toBasetype();
1231 switch (t.ty)
1233 case Tvector:
1234 t = t.isTypeVector().basetype;
1235 goto case Tsarray;
1237 case Tsarray:
1238 uinteger_t adim = t.isTypeSArray().dim.toInteger();
1239 if (adim >= amax)
1240 return null;
1241 edim = cast(uint)adim;
1242 break;
1244 case Tpointer:
1245 case Tarray:
1246 edim = init.dim;
1247 break;
1249 default:
1250 assert(0);
1253 else
1255 /* Calculate the length of the array literal
1257 edim = cast(uint)init.value.length;
1258 size_t j = 0;
1259 foreach (i; 0 .. init.value.length)
1261 if (auto e = init.index[i])
1263 if (e.op == EXP.int64)
1265 const uinteger_t idxval = e.toInteger();
1266 if (idxval >= amax)
1267 return null;
1268 j = cast(size_t)idxval;
1270 else
1271 return null;
1273 ++j;
1274 if (j > edim)
1275 edim = cast(uint)j;
1279 auto elements = new Expressions(edim);
1280 elements.zero();
1281 size_t j = 0;
1282 foreach (i; 0 .. init.value.length)
1284 if (auto e = init.index[i])
1285 j = cast(size_t)e.toInteger();
1286 assert(j < edim);
1287 if (Initializer iz = init.value[i])
1289 if (Expression ex = iz.initializerToExpression(null, isCfile))
1291 (*elements)[j] = ex;
1292 ++j;
1294 else
1295 return null;
1297 else
1298 return null;
1301 /* Fill in any missing elements with the default initializer
1303 Expression defaultInit = null; // lazily create it
1304 foreach (ref element; (*elements)[0 .. edim])
1306 if (!element)
1308 if (!init.type) // don't know what type to use
1309 return null;
1310 if (!defaultInit)
1311 defaultInit = (cast(TypeNext)t).next.defaultInit(Loc.initial, isCfile);
1312 element = defaultInit;
1316 /* Expand any static array initializers that are a single expression
1317 * into an array of them
1318 * e => [e, e, ..., e, e]
1320 if (t)
1322 Type tn = t.nextOf().toBasetype();
1323 if (tn.ty == Tsarray)
1325 const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger();
1326 Type te = tn.nextOf().toBasetype();
1327 foreach (ref e; *elements)
1329 if (te.equals(e.type))
1331 auto elements2 = new Expressions(dim);
1332 foreach (ref e2; *elements2)
1333 e2 = e;
1334 e = new ArrayLiteralExp(e.loc, tn, elements2);
1340 /* If any elements are errors, then the whole thing is an error
1342 foreach (e; (*elements)[0 .. edim])
1344 if (e.op == EXP.error)
1346 return e;
1350 Expression e = new ArrayLiteralExp(init.loc, init.type, elements);
1351 return e;
1354 Expression visitExp(ExpInitializer i)
1356 if (itype)
1358 //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
1359 Type tb = itype.toBasetype();
1360 Expression e = (i.exp.op == EXP.construct || i.exp.op == EXP.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
1361 if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
1363 TypeSArray tsa = cast(TypeSArray)tb;
1364 size_t d = cast(size_t)tsa.dim.toInteger();
1365 auto elements = new Expressions(d);
1366 for (size_t j = 0; j < d; j++)
1367 (*elements)[j] = e;
1368 auto ae = new ArrayLiteralExp(e.loc, itype, elements);
1369 return ae;
1372 return i.exp;
1375 Expression visitC(CInitializer i)
1377 //printf("CInitializer.initializerToExpression(null, true)\n");
1378 return null;
1381 mixin VisitInitializer!Expression visit;
1382 return visit.VisitInitializer(init);
1386 /**************************************
1387 * Determine if expression has non-constant pointers, or more precisely,
1388 * a pointer that CTFE cannot handle.
1389 * Params:
1390 * e = expression to check
1391 * Returns:
1392 * true if it has non-constant pointers
1394 private bool hasNonConstPointers(Expression e)
1396 static bool checkArray(Expressions* elems)
1398 foreach (e; *elems)
1400 if (e && hasNonConstPointers(e))
1401 return true;
1403 return false;
1406 if (e.type.ty == Terror)
1407 return false;
1408 if (e.op == EXP.null_)
1409 return false;
1410 if (auto se = e.isStructLiteralExp())
1412 return checkArray(se.elements);
1414 if (auto ae = e.isArrayLiteralExp())
1416 if (!ae.type.nextOf().hasPointers())
1417 return false;
1418 return checkArray(ae.elements);
1420 if (auto ae = e.isAssocArrayLiteralExp())
1422 if (ae.type.nextOf().hasPointers() && checkArray(ae.values))
1423 return true;
1424 if (ae.type.isTypeAArray().index.hasPointers())
1425 return checkArray(ae.keys);
1426 return false;
1428 if (auto ae = e.isAddrExp())
1430 if (ae.type.nextOf().isImmutable() || ae.type.nextOf().isConst())
1432 return false;
1434 if (auto se = ae.e1.isStructLiteralExp())
1436 if (!(se.stageflags & stageSearchPointers))
1438 const old = se.stageflags;
1439 se.stageflags |= stageSearchPointers;
1440 bool ret = checkArray(se.elements);
1441 se.stageflags = old;
1442 return ret;
1444 else
1446 return false;
1449 return true;
1451 if (e.type.ty == Tpointer && !e.type.isPtrToFunction())
1453 if (e.op == EXP.symbolOffset) // address of a global is OK
1454 return false;
1455 if (e.op == EXP.int64) // cast(void *)int is OK
1456 return false;
1457 if (e.op == EXP.string_) // "abc".ptr is OK
1458 return false;
1459 return true;
1461 return false;
1465 Given the names and values of a `StructInitializer` or `CallExp`,
1466 resolve it to a list of expressions to construct a `StructLiteralExp`.
1468 Params:
1469 sd = struct
1470 t = type of struct (potentially including qualifiers such as `const` or `immutable`)
1471 sc = scope of the expression initializing the struct
1472 iloc = location of expression initializing the struct
1473 names = identifiers passed in argument list, `null` entries for positional arguments
1474 getExp = function that, given an index into `names` and destination type, returns the initializing expression
1475 getLoc = function that, given an index into `names`, returns a location for error messages
1477 Returns: list of expressions ordered to the struct's fields, or `null` on error
1479 Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* sc,
1480 Loc iloc, Identifier[] names, scope Expression delegate(size_t i, Type fieldType) getExp,
1481 scope Loc delegate(size_t i) getLoc
1484 //expandTuples for non-identity arguments?
1485 const nfields = sd.nonHiddenFields();
1486 auto elements = new Expressions(nfields);
1487 auto elems = (*elements)[];
1488 foreach (ref elem; elems)
1489 elem = null;
1491 // Run semantic for explicitly given initializers
1492 // TODO: this part is slightly different from StructLiteralExp::semantic.
1493 bool errors = false;
1494 size_t fieldi = 0;
1495 foreach (j, id; names)
1497 const argLoc = getLoc(j);
1498 if (id)
1500 // Determine `fieldi` that `id` matches
1501 Dsymbol s = sd.search(iloc, id);
1502 if (!s)
1504 s = sd.search_correct(id);
1505 if (s)
1506 error(argLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars());
1507 else
1508 error(argLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars());
1509 return null;
1511 s.checkDeprecated(iloc, sc);
1512 s = s.toAlias();
1514 // Find out which field index `s` is
1515 for (fieldi = 0; 1; fieldi++)
1517 if (fieldi >= nfields)
1519 error(iloc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars());
1520 return null;
1522 if (s == sd.fields[fieldi])
1523 break;
1526 if (nfields == 0)
1528 error(argLoc, "initializer provided for struct `%s` with no fields", sd.toChars());
1529 return null;
1531 if (j >= nfields)
1533 error(argLoc, "too many initializers for `%s` with %d field%s", sd.toChars(),
1534 cast(int) nfields, nfields != 1 ? "s".ptr : "".ptr);
1535 return null;
1538 VarDeclaration vd = sd.fields[fieldi];
1539 if (elems[fieldi])
1541 error(argLoc, "duplicate initializer for field `%s`", vd.toChars());
1542 errors = true;
1543 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
1544 ++fieldi;
1545 continue;
1548 // Check for @safe violations
1549 if (vd.type.hasPointers)
1551 if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize ||
1552 (vd.offset & (target.ptrsize - 1))))
1554 if (sc.setUnsafe(false, argLoc,
1555 "field `%s.%s` cannot assign to misaligned pointers in `@safe` code", sd, vd))
1557 errors = true;
1558 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
1559 ++fieldi;
1560 continue;
1565 // Check for overlapping initializations (can happen with unions)
1566 foreach (k, v2; sd.fields[0 .. nfields])
1568 if (vd.isOverlappedWith(v2) && elems[k])
1570 error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
1571 enum errorMsg = "`struct` initializers that contain anonymous unions" ~
1572 " must initialize only the first member of a `union`. All subsequent" ~
1573 " non-overlapping fields are default initialized";
1574 if (!sd.isUnionDeclaration())
1575 .errorSupplemental(elems[k].loc, errorMsg);
1576 errors = true;
1577 continue;
1581 assert(sc);
1583 auto ex = getExp(j, vd.type);
1585 if (ex.op == EXP.error)
1587 errors = true;
1588 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
1589 ++fieldi;
1590 continue;
1593 elems[fieldi] = doCopyOrMove(sc, ex);
1594 ++fieldi;
1596 if (errors)
1597 return null;
1599 return elements;