1 /**
2 * Semantic analysis of initializers.
3 *
4 * Copyright: Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
5 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright)
6 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/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
10 */
11
12 module dmd.initsem;
13
14 import core.stdc.stdio;
15 import core.checkedint;
16
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.id;
33 import dmd.identifier;
34 import dmd.importc;
35 import dmd.init;
36 import dmd.mtype;
37 import dmd.opover;
38 import dmd.statement;
39 import dmd.target;
40 import dmd.tokens;
41 import dmd.typesem;
42
43 /********************************
44 * If possible, convert array initializer to associative array initializer.
45 *
46 * Params:
47 * ai = array initializer to be converted
48 *
49 * Returns:
50 * The converted associative array initializer or ErrorExp if `ai`
51 * is not an associative array initializer.
52 */
toAssocArrayLiteral(ArrayInitializer ai)53 Expression toAssocArrayLiteral(ArrayInitializer ai)
54 {
55 Expression e;
56 //printf("ArrayInitializer::toAssocArrayInitializer()\n");
57 //static int i; if (++i == 2) assert(0);
58 const dim = ai.value.dim;
59 auto keys = new Expressions(dim);
60 auto values = new Expressions(dim);
61 for (size_t i = 0; i < dim; i++)
62 {
63 e = ai.index[i];
64 if (!e)
65 goto Lno;
66 (*keys)[i] = e;
67 Initializer iz = ai.value[i];
68 if (!iz)
69 goto Lno;
70 e = iz.initializerToExpression();
71 if (!e)
72 goto Lno;
73 (*values)[i] = e;
74 }
75 e = new AssocArrayLiteralExp(ai.loc, keys, values);
76 return e;
77 Lno:
78 error(ai.loc, "not an associative array initializer");
79 return ErrorExp.get();
80 }
81
82 /******************************************
83 * Perform semantic analysis on init.
84 * Params:
85 * init = Initializer AST node
86 * sc = context
87 * tx = type that the initializer needs to become. If tx is an incomplete
88 * type and the initializer completes it, it is updated to be the
89 * complete type. ImportC has incomplete types
90 * needInterpret = if CTFE needs to be run on this,
91 * such as if it is the initializer for a const declaration
92 * Returns:
93 * `Initializer` with completed semantic analysis, `ErrorInitializer` if errors
94 * were encountered
95 */
initializerSemantic(Initializer init,Scope * sc,ref Type tx,NeedInterpret needInterpret)96 extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret)
97 {
98 Type t = tx;
99
100 static Initializer err()
101 {
102 return new ErrorInitializer();
103 }
104
105 Initializer visitVoid(VoidInitializer i)
106 {
107 i.type = t;
108 return i;
109 }
110
111 Initializer visitError(ErrorInitializer i)
112 {
113 return i;
114 }
115
116 Initializer visitStruct(StructInitializer i)
117 {
118 //printf("StructInitializer::semantic(t = %s) %s\n", t.toChars(), i.toChars());
119 /* This works by replacing the StructInitializer with an ExpInitializer.
120 */
121 t = t.toBasetype();
122 if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct)
123 t = t.nextOf().toBasetype();
124 if (auto ts = t.isTypeStruct())
125 {
126 StructDeclaration sd = ts.sym;
127 // check if the sd has a regular ctor (user defined non-copy ctor)
128 // that is not disabled.
129 if (sd.hasRegularCtor(true))
130 {
131 error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars());
132 return err();
133 }
134 sd.size(i.loc);
135 if (sd.sizeok != Sizeok.done)
136 return err();
137 const nfields = sd.nonHiddenFields();
138 //expandTuples for non-identity arguments?
139 auto elements = new Expressions(nfields);
140 auto elems = (*elements)[];
141 foreach (ref elem; elems)
142 elem = null;
143
144 // Run semantic for explicitly given initializers
145 // TODO: this part is slightly different from StructLiteralExp::semantic.
146 bool errors = false;
147 size_t fieldi = 0;
148 foreach (j, id; i.field[])
149 {
150 if (id)
151 {
152 /* Determine `fieldi` that `id` matches
153 */
154 Dsymbol s = sd.search(i.loc, id);
155 if (!s)
156 {
157 s = sd.search_correct(id);
158 const initLoc = i.value[j].loc;
159 if (s)
160 error(initLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars());
161 else
162 error(initLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars());
163 return err();
164 }
165 s.checkDeprecated(i.loc, sc);
166 s = s.toAlias();
167
168 // Find out which field index `s` is
169 for (fieldi = 0; 1; fieldi++)
170 {
171 if (fieldi >= nfields)
172 {
173 error(i.loc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars());
174 return err();
175 }
176 if (s == sd.fields[fieldi])
177 break;
178 }
179 }
180 if (j >= nfields)
181 {
182 error(i.value[j].loc, "too many initializers for `%s`", sd.toChars());
183 return err();
184 }
185
186 VarDeclaration vd = sd.fields[fieldi];
187 if (elems[fieldi])
188 {
189 error(i.value[j].loc, "duplicate initializer for field `%s`", vd.toChars());
190 errors = true;
191 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
192 ++fieldi;
193 continue;
194 }
195
196 // Check for @safe violations
197 if (vd.type.hasPointers)
198 {
199 if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize ||
200 (vd.offset & (target.ptrsize - 1))) &&
201 sc.func && sc.func.setUnsafe())
202 {
203 error(i.value[j].loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
204 sd.toChars(), vd.toChars());
205 errors = true;
206 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
207 ++fieldi;
208 continue;
209 }
210 }
211
212 // Check for overlapping initializations (can happen with unions)
213 foreach (k, v2; sd.fields[0 .. nfields])
214 {
215 if (vd.isOverlappedWith(v2) && elems[k])
216 {
217 error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
218 errors = true;
219 continue;
220 }
221 }
222
223 // Convert initializer to Expression `ex`
224 assert(sc);
225 auto tm = vd.type.addMod(t.mod);
226 auto iz = i.value[j].initializerSemantic(sc, tm, needInterpret);
227 auto ex = iz.initializerToExpression();
228 if (ex.op == EXP.error)
229 {
230 errors = true;
231 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
232 ++fieldi;
233 continue;
234 }
235
236 i.value[j] = iz;
237 elems[fieldi] = doCopyOrMove(sc, ex);
238 ++fieldi;
239 }
240 if (errors)
241 return err();
242
243 // Make a StructLiteralExp out of elements[]
244 auto sle = new StructLiteralExp(i.loc, sd, elements, t);
245 if (!sd.fill(i.loc, elements, false))
246 return err();
247 sle.type = t;
248 auto ie = new ExpInitializer(i.loc, sle);
249 return ie.initializerSemantic(sc, t, needInterpret);
250 }
251 else if ((t.ty == Tdelegate || t.isPtrToFunction()) && i.value.dim == 0)
252 {
253 const tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_;
254 /* Rewrite as empty delegate literal { }
255 */
256 Type tf = new TypeFunction(ParameterList(), null, LINK.d);
257 auto fd = new FuncLiteralDeclaration(i.loc, Loc.initial, tf, tok, null);
258 fd.fbody = new CompoundStatement(i.loc, new Statements());
259 fd.endloc = i.loc;
260 Expression e = new FuncExp(i.loc, fd);
261 auto ie = new ExpInitializer(i.loc, e);
262 return ie.initializerSemantic(sc, t, needInterpret);
263 }
264 if (t.ty != Terror)
265 error(i.loc, "a struct is not a valid initializer for a `%s`", t.toChars());
266 return err();
267 }
268
269 Initializer visitArray(ArrayInitializer i)
270 {
271 uint length;
272 const(uint) amax = 0x80000000;
273 bool errors = false;
274 //printf("ArrayInitializer::semantic(%s)\n", t.toChars());
275 if (i.sem) // if semantic() already run
276 {
277 return i;
278 }
279 i.sem = true;
280 t = t.toBasetype();
281 switch (t.ty)
282 {
283 case Tsarray:
284 case Tarray:
285 break;
286 case Tvector:
287 t = t.isTypeVector().basetype;
288 break;
289 case Taarray:
290 case Tstruct: // consider implicit constructor call
291 {
292 Expression e;
293 // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int])
294 if (t.ty == Taarray || i.isAssociativeArray())
295 e = i.toAssocArrayLiteral();
296 else
297 e = i.initializerToExpression();
298 // Bugzilla 13987
299 if (!e)
300 {
301 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
302 return err();
303 }
304 auto ei = new ExpInitializer(e.loc, e);
305 return ei.initializerSemantic(sc, t, needInterpret);
306 }
307 case Tpointer:
308 if (t.nextOf().ty != Tfunction)
309 break;
310 goto default;
311 default:
312 error(i.loc, "cannot use array to initialize `%s`", t.toChars());
313 return err();
314 }
315 i.type = t;
316 length = 0;
317 for (size_t j = 0; j < i.index.dim; j++)
318 {
319 Expression idx = i.index[j];
320 if (idx)
321 {
322 sc = sc.startCTFE();
323 idx = idx.expressionSemantic(sc);
324 sc = sc.endCTFE();
325 idx = idx.ctfeInterpret();
326 i.index[j] = idx;
327 const uinteger_t idxvalue = idx.toInteger();
328 if (idxvalue >= amax)
329 {
330 error(i.loc, "array index %llu overflow", idxvalue);
331 errors = true;
332 }
333 length = cast(uint)idxvalue;
334 if (idx.op == EXP.error)
335 errors = true;
336 }
337 Initializer val = i.value[j];
338 ExpInitializer ei = val.isExpInitializer();
339 if (ei && !idx)
340 ei.expandTuples = true;
341 auto tn = t.nextOf();
342 val = val.initializerSemantic(sc, tn, needInterpret);
343 if (val.isErrorInitializer())
344 errors = true;
345 ei = val.isExpInitializer();
346 // found a tuple, expand it
347 if (ei && ei.exp.op == EXP.tuple)
348 {
349 TupleExp te = ei.exp.isTupleExp();
350 i.index.remove(j);
351 i.value.remove(j);
352 for (size_t k = 0; k < te.exps.dim; ++k)
353 {
354 Expression e = (*te.exps)[k];
355 i.index.insert(j + k, cast(Expression)null);
356 i.value.insert(j + k, new ExpInitializer(e.loc, e));
357 }
358 j--;
359 continue;
360 }
361 else
362 {
363 i.value[j] = val;
364 }
365 length++;
366 if (length == 0)
367 {
368 error(i.loc, "array dimension overflow");
369 return err();
370 }
371 if (length > i.dim)
372 i.dim = length;
373 }
374 if (auto tsa = t.isTypeSArray())
375 {
376 uinteger_t edim = tsa.dim.toInteger();
377 if (i.dim > edim && !(tsa.isIncomplete() && (sc.flags & SCOPE.Cfile)))
378 {
379 error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
380 return err();
381 }
382 }
383 if (errors)
384 return err();
385
386 const sz = t.nextOf().size();
387 if (sz == SIZE_INVALID)
388 return err();
389 bool overflow;
390 const max = mulu(i.dim, sz, overflow);
391 if (overflow || max >= amax)
392 {
393 error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz));
394 return err();
395 }
396 return i;
397 }
398
399 Initializer visitExp(ExpInitializer i)
400 {
401 //printf("ExpInitializer::semantic(%s), type = %s\n", i.exp.toChars(), t.toChars());
402 if (needInterpret)
403 sc = sc.startCTFE();
404 i.exp = i.exp.expressionSemantic(sc);
405 i.exp = resolveProperties(sc, i.exp);
406 if (needInterpret)
407 sc = sc.endCTFE();
408 if (i.exp.op == EXP.error)
409 return err();
410 uint olderrors = global.errors;
411
412 /* ImportC: convert arrays to pointers, functions to pointers to functions
413 */
414 Type tb = t.toBasetype();
415 if (tb.isTypePointer())
416 i.exp = i.exp.arrayFuncConv(sc);
417
418 /* Save the expression before ctfe
419 * Otherwise the error message would contain for example "&[0][0]" instead of "new int"
420 * Regression: https://issues.dlang.org/show_bug.cgi?id=21687
421 */
422 Expression currExp = i.exp;
423 if (needInterpret)
424 {
425 // If the result will be implicitly cast, move the cast into CTFE
426 // to avoid premature truncation of polysemous types.
427 // eg real [] x = [1.1, 2.2]; should use real precision.
428 if (i.exp.implicitConvTo(t) && !(sc.flags & SCOPE.Cfile))
429 {
430 i.exp = i.exp.implicitCastTo(sc, t);
431 }
432 if (!global.gag && olderrors != global.errors)
433 {
434 return i;
435 }
436 if (sc.flags & SCOPE.Cfile)
437 {
438 /* the interpreter turns (char*)"string" into &"string"[0] which then
439 * it cannot interpret. Resolve that case by doing optimize() first
440 */
441 i.exp = i.exp.optimize(WANTvalue);
442 if (i.exp.isSymOffExp())
443 {
444 /* `static variable cannot be read at compile time`
445 * https://issues.dlang.org/show_bug.cgi?id=22513
446 * Maybe this would be better addressed in ctfeInterpret()?
447 */
448 needInterpret = NeedInterpret.INITnointerpret;
449 }
450 }
451 if (needInterpret)
452 i.exp = i.exp.ctfeInterpret();
453 if (i.exp.op == EXP.voidExpression)
454 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
455 }
456 else
457 {
458 i.exp = i.exp.optimize(WANTvalue);
459 }
460
461 if (!global.gag && olderrors != global.errors)
462 {
463 return i; // Failed, suppress duplicate error messages
464 }
465 if (i.exp.type.isTypeTuple() && i.exp.type.isTypeTuple().arguments.dim == 0)
466 {
467 Type et = i.exp.type;
468 i.exp = new TupleExp(i.exp.loc, new Expressions());
469 i.exp.type = et;
470 }
471 if (i.exp.op == EXP.type)
472 {
473 i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars());
474 return err();
475 }
476 // Make sure all pointers are constants
477 if (needInterpret && hasNonConstPointers(i.exp))
478 {
479 i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
480 return err();
481 }
482 Type ti = i.exp.type.toBasetype();
483 if (i.exp.op == EXP.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
484 {
485 return new ExpInitializer(i.loc, i.exp);
486 }
487 /* Look for case of initializing a static array with a too-short
488 * string literal, such as:
489 * char[5] foo = "abc";
490 * Allow this by doing an explicit cast, which will lengthen the string
491 * literal.
492 */
493 if (i.exp.op == EXP.string_ && tb.ty == Tsarray)
494 {
495 StringExp se = i.exp.isStringExp();
496 Type typeb = se.type.toBasetype();
497 TY tynto = tb.nextOf().ty;
498 if (!se.committed &&
499 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
500 se.numberOfCodeUnits(tynto) < tb.isTypeSArray().dim.toInteger())
501 {
502 i.exp = se.castTo(sc, t);
503 goto L1;
504 }
505
506 /* Lop off terminating 0 of initializer for:
507 * static char s[5] = "hello";
508 */
509 if (sc.flags & SCOPE.Cfile &&
510 typeb.ty == Tsarray &&
511 tynto.isSomeChar &&
512 tb.isTypeSArray().dim.toInteger() + 1 == typeb.isTypeSArray().dim.toInteger())
513 {
514 i.exp = se.castTo(sc, t);
515 goto L1;
516 }
517 }
518 /* C11 6.7.9-14..15
519 * Initialize an array of unknown size with a string.
520 * Change to static array of known size
521 */
522 if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
523 tb.isTypeSArray() && tb.isTypeSArray().isIncomplete())
524 {
525 StringExp se = i.exp.isStringExp();
526 auto ts = new TypeSArray(tb.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
527 t = typeSemantic(ts, Loc.initial, sc);
528 i.exp.type = t;
529 tx = t;
530 }
531
532 // Look for implicit constructor call
533 if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t))
534 {
535 StructDeclaration sd = tb.isTypeStruct().sym;
536 if (sd.ctor)
537 {
538 // Rewrite as S().ctor(exp)
539 Expression e;
540 e = new StructLiteralExp(i.loc, sd, null);
541 e = new DotIdExp(i.loc, e, Id.ctor);
542 e = new CallExp(i.loc, e, i.exp);
543 e = e.expressionSemantic(sc);
544 if (needInterpret)
545 i.exp = e.ctfeInterpret();
546 else
547 i.exp = e.optimize(WANTvalue);
548 }
549 else if (search_function(sd, Id.call))
550 {
551 /* https://issues.dlang.org/show_bug.cgi?id=1547
552 *
553 * Look for static opCall
554 *
555 * Rewrite as:
556 * i.exp = typeof(sd).opCall(arguments)
557 */
558
559 Expression e = typeDotIdExp(i.loc, sd.type, Id.call);
560 e = new CallExp(i.loc, e, i.exp);
561 e = e.expressionSemantic(sc);
562 e = resolveProperties(sc, e);
563 if (needInterpret)
564 i.exp = e.ctfeInterpret();
565 else
566 i.exp = e.optimize(WANTvalue);
567 }
568 }
569 {
570 // Look for the case of statically initializing an array
571 // with a single member.
572 auto tba = tb.isTypeSArray();
573 if (tba && !tba.next.equals(ti.toBasetype().nextOf()) && i.exp.implicitConvTo(tba.next))
574 {
575 /* If the variable is not actually used in compile time, array creation is
576 * redundant. So delay it until invocation of toExpression() or toDt().
577 */
578 t = tb.nextOf();
579 }
580
581 auto tta = t.isTypeSArray();
582 if (i.exp.implicitConvTo(t))
583 {
584 i.exp = i.exp.implicitCastTo(sc, t);
585 }
586 else if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
587 tta && (tta.next.ty == Tint8 || tta.next.ty == Tuns8) &&
588 ti.ty == Tpointer && ti.nextOf().ty == Tchar)
589 {
590 /* unsigned char bbb[1] = "";
591 * signed char ccc[1] = "";
592 */
593 i.exp = i.exp.castTo(sc, t);
594 }
595 else
596 {
597 // Look for mismatch of compile-time known length to emit
598 // better diagnostic message, as same as AssignExp::semantic.
599 if (tba && i.exp.implicitConvTo(tba.next.arrayOf()) > MATCH.nomatch)
600 {
601 uinteger_t dim1 = tba.dim.toInteger();
602 uinteger_t dim2 = dim1;
603 if (auto ale = i.exp.isArrayLiteralExp())
604 {
605 dim2 = ale.elements ? ale.elements.dim : 0;
606 }
607 else if (auto se = i.exp.isSliceExp())
608 {
609 if (Type tx = toStaticArrayType(se))
610 dim2 = tx.isTypeSArray().dim.toInteger();
611 }
612 if (dim1 != dim2)
613 {
614 i.exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
615 i.exp = ErrorExp.get();
616 }
617 }
618 Type et = i.exp.type;
619 const errors = global.startGagging();
620 i.exp = i.exp.implicitCastTo(sc, t);
621 if (global.endGagging(errors))
622 currExp.error("cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toChars(), et.toChars(), t.toChars());
623 }
624 }
625 L1:
626 if (i.exp.op == EXP.error)
627 {
628 return i;
629 }
630 if (needInterpret)
631 i.exp = i.exp.ctfeInterpret();
632 else
633 i.exp = i.exp.optimize(WANTvalue);
634 //printf("-ExpInitializer::semantic(): "); i.exp.print();
635 return i;
636 }
637
638 Initializer visitC(CInitializer ci)
639 {
640 if (ci.sem) // if semantic() already run
641 return ci;
642 //printf("CInitializer::semantic() (%s) %s\n", t.toChars(), ci.toChars());
643 ci.sem = true;
644 t = t.toBasetype();
645 ci.type = t; // later passes will need this
646
647 auto dil = ci.initializerList[];
648 size_t i = 0; // index into dil[]
649 const uint amax = 0x8000_0000;
650 bool errors;
651
652 /* If `{ expression }` return the expression initializer
653 */
654 ExpInitializer isBraceExpression()
655 {
656 return (dil.length == 1 && !dil[0].designatorList)
657 ? dil[0].initializer.isExpInitializer()
658 : null;
659 }
660
661 /* Convert struct initializer into ExpInitializer
662 */
663 Initializer structs(TypeStruct ts)
664 {
665 //printf("structs %s\n", ts.toChars());
666 StructDeclaration sd = ts.sym;
667 sd.size(ci.loc);
668 if (sd.sizeok != Sizeok.done)
669 {
670 errors = true;
671 return err();
672 }
673 const nfields = sd.nonHiddenFields();
674 auto elements = new Expressions(nfields);
675 auto elems = (*elements)[];
676 foreach (ref elem; elems)
677 elem = null;
678
679 FieldLoop:
680 for (size_t fieldi = 0; fieldi < nfields; ++fieldi)
681 {
682 if (i == dil.length)
683 break;
684
685 auto di = dil[i];
686 if (di.designatorList)
687 {
688 error(ci.loc, "C designator-list not supported yet");
689 errors = true;
690 break;
691 }
692
693 VarDeclaration vd = sd.fields[fieldi];
694
695 // Check for overlapping initializations (can happen with unions)
696 foreach (k, v2; sd.fields[0 .. nfields])
697 {
698 if (vd.isOverlappedWith(v2) && elems[k])
699 {
700 continue FieldLoop; // skip it
701 }
702 }
703
704 ++i;
705
706 // Convert initializer to Expression `ex`
707 assert(sc);
708 auto tm = vd.type.addMod(ts.mod);
709 auto iz = di.initializer.initializerSemantic(sc, tm, needInterpret);
710 auto ex = iz.initializerToExpression(null, true);
711 if (ex.op == EXP.error)
712 {
713 errors = true;
714 continue;
715 }
716
717 elems[fieldi] = ex;
718 }
719 if (errors)
720 return err();
721
722 // Make a StructLiteralExp out of elements[]
723 Type tx = ts;
724 auto sle = new StructLiteralExp(ci.loc, sd, elements, tx);
725 if (!sd.fill(ci.loc, elements, false))
726 return err();
727 sle.type = tx;
728 auto ie = new ExpInitializer(ci.loc, sle);
729 return ie.initializerSemantic(sc, tx, needInterpret);
730 }
731
732 if (auto ts = t.isTypeStruct())
733 {
734 auto ei = structs(ts);
735 if (errors)
736 return err();
737 if (i < dil.length)
738 {
739 error(ci.loc, "%d extra initializer(s) for `struct %s`", cast(int)(dil.length - i), ts.toChars());
740 return err();
741 }
742 return ei;
743 }
744
745 auto tsa = t.isTypeSArray();
746 if (!tsa)
747 {
748 /* Not an array. See if it is `{ exp }` which can be
749 * converted to an ExpInitializer
750 */
751 if (ExpInitializer ei = isBraceExpression())
752 {
753 return ei.initializerSemantic(sc, t, needInterpret);
754 }
755
756 error(ci.loc, "C non-array initializer (%s) %s not supported yet", t.toChars(), ci.toChars());
757 return err();
758 }
759
760 /* If it's an array of integral being initialized by `{ string }`
761 * replace with `string`
762 */
763 auto tn = t.nextOf();
764 if (tn.isintegral())
765 {
766 if (ExpInitializer ei = isBraceExpression())
767 {
768 if (ei.exp.isStringExp())
769 return ei.initializerSemantic(sc, t, needInterpret);
770 }
771 }
772
773 /* Support recursion to handle un-braced array initializers
774 * Params:
775 * t = element type
776 * dim = max number of elements
777 * simple = true if array of simple elements
778 * Returns:
779 * # of elements in array
780 */
781 size_t array(Type t, size_t dim, ref bool simple)
782 {
783 //printf(" type %s i %d dim %d dil.length = %d\n", t.toChars(), cast(int)i, cast(int)dim, cast(int)dil.length);
784 auto tn = t.nextOf().toBasetype();
785 auto tnsa = tn.isTypeSArray();
786 if (tnsa && tnsa.isIncomplete())
787 {
788 // C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
789 error(ci.loc, "incomplete element type `%s` not allowed", tnsa.toChars());
790 errors = true;
791 return 1;
792 }
793 if (i == dil.length)
794 return 0;
795 size_t n;
796 const nelems = tnsa ? cast(size_t)tnsa.dim.toInteger() : 0;
797
798 /* Run initializerSemantic on a single element.
799 */
800 Initializer elem(Initializer ie)
801 {
802 ++i;
803 auto tnx = tn; // in case initializerSemantic tries to change it
804 ie = ie.initializerSemantic(sc, tnx, needInterpret);
805 if (ie.isErrorInitializer())
806 errors = true;
807 assert(tnx == tn); // sub-types should not be modified
808 return ie;
809 }
810
811 foreach (j; 0 .. dim)
812 {
813 auto di = dil[i];
814 if (di.designatorList)
815 {
816 error(ci.loc, "C designator-list not supported yet");
817 errors = true;
818 break;
819 }
820 if (tnsa && di.initializer.isExpInitializer())
821 {
822 // no braces enclosing array initializer, so recurse
823 array(tnsa, nelems, simple);
824 }
825 else if (auto tns = tn.isTypeStruct())
826 {
827 if (auto ei = di.initializer.isExpInitializer())
828 {
829 // no braces enclosing struct initializer
830
831 /* Disambiguate between an exp representing the entire
832 * struct, and an exp representing the first field of the struct
833 */
834 if (needInterpret)
835 sc = sc.startCTFE();
836 ei.exp = ei.exp.expressionSemantic(sc);
837 ei.exp = resolveProperties(sc, ei.exp);
838 if (needInterpret)
839 sc = sc.endCTFE();
840 if (ei.exp.implicitConvTo(tn))
841 di.initializer = elem(di.initializer); // the whole struct
842 else
843 {
844 simple = false;
845 dil[n].initializer = structs(tns); // the first field
846 }
847 }
848 else
849 dil[n].initializer = elem(di.initializer);
850 }
851 else
852 {
853 di.initializer = elem(di.initializer);
854 }
855 ++n;
856 if (i == dil.length)
857 break;
858 }
859 //printf(" n: %d i: %d\n", cast(int)n, cast(int)i);
860 return n;
861 }
862
863 size_t dim = tsa.isIncomplete() ? dil.length : cast(size_t)tsa.dim.toInteger();
864 bool simple = true;
865 auto newdim = array(t, dim, simple);
866
867 if (errors)
868 return err();
869
870 if (tsa.isIncomplete()) // array of unknown length
871 {
872 // Change to array of known length
873 tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, newdim, Type.tsize_t));
874 tx = tsa; // rewrite caller's type
875 ci.type = tsa; // remember for later passes
876 }
877 const uinteger_t edim = tsa.dim.toInteger();
878 if (i < dil.length)
879 {
880 error(ci.loc, "%d extra initializer(s) for static array length of %d", cast(int)(dil.length - i), cast(int)edim);
881 return err();
882 }
883
884 const sz = tn.size(); // element size
885 if (sz == SIZE_INVALID)
886 return err();
887 bool overflow;
888 const max = mulu(edim, sz, overflow);
889 if (overflow || max >= amax)
890 {
891 error(ci.loc, "array dimension %llu exceeds max of %llu", ulong(edim), ulong(amax / sz));
892 return err();
893 }
894
895 /* If an array of simple elements, replace with an ArrayInitializer
896 */
897 auto tnb = tn.toBasetype();
898 if (!tnb.isTypeSArray() && (!tnb.isTypeStruct() || simple))
899 {
900 auto ai = new ArrayInitializer(ci.loc);
901 ai.dim = cast(uint) dil.length;
902 ai.index.setDim(dil.length);
903 ai.value.setDim(dil.length);
904 foreach (const j; 0 .. dil.length)
905 {
906 ai.index[j] = null;
907 ai.value[j] = dil[j].initializer;
908 }
909 auto ty = tx;
910 return ai.initializerSemantic(sc, ty, needInterpret);
911 }
912
913 if (newdim < ci.initializerList.length && tnb.isTypeStruct())
914 {
915 // https://issues.dlang.org/show_bug.cgi?id=22375
916 // initializerList can be bigger than the number of actual elements
917 // to initialize for array of structs because it is not required
918 // for values to have proper bracing.
919 // i.e: These are all valid initializers for `struct{int a,b;}[3]`:
920 // {1,2,3,4}, {{1,2},3,4}, {1,2,{3,4}}, {{1,2},{3,4}}
921 // In all examples above, the new length of the initializer list
922 // has been shortened from four elements to two. This is important,
923 // because `dil` is written back to directly, making the lowered
924 // initializer `{{1,2},{3,4}}` and not `{{1,2},{3,4},3,4}`.
925 ci.initializerList.length = newdim;
926 }
927
928 return ci;
929 }
930
931 final switch (init.kind)
932 {
933 case InitKind.void_: return visitVoid (init.isVoidInitializer());
934 case InitKind.error: return visitError (init.isErrorInitializer());
935 case InitKind.struct_: return visitStruct(init.isStructInitializer());
936 case InitKind.array: return visitArray (init.isArrayInitializer());
937 case InitKind.exp: return visitExp (init.isExpInitializer());
938 case InitKind.C_: return visitC (init.isCInitializer());
939 }
940 }
941
942 /***********************
943 * Translate init to an `Expression` in order to infer the type.
944 * Params:
945 * init = `Initializer` AST node
946 * sc = context
947 * Returns:
948 * an equivalent `ExpInitializer` if successful, or `ErrorInitializer` if it cannot be translated
949 */
inferType(Initializer init,Scope * sc)950 Initializer inferType(Initializer init, Scope* sc)
951 {
952 Initializer visitVoid(VoidInitializer i)
953 {
954 error(i.loc, "cannot infer type from void initializer");
955 return new ErrorInitializer();
956 }
957
958 Initializer visitError(ErrorInitializer i)
959 {
960 return i;
961 }
962
963 Initializer visitStruct(StructInitializer i)
964 {
965 error(i.loc, "cannot infer type from struct initializer");
966 return new ErrorInitializer();
967 }
968
969 Initializer visitArray(ArrayInitializer init)
970 {
971 //printf("ArrayInitializer::inferType() %s\n", toChars());
972 Expressions* keys = null;
973 Expressions* values;
974 if (init.isAssociativeArray())
975 {
976 keys = new Expressions(init.value.dim);
977 values = new Expressions(init.value.dim);
978 for (size_t i = 0; i < init.value.dim; i++)
979 {
980 Expression e = init.index[i];
981 if (!e)
982 goto Lno;
983 (*keys)[i] = e;
984 Initializer iz = init.value[i];
985 if (!iz)
986 goto Lno;
987 iz = iz.inferType(sc);
988 if (iz.isErrorInitializer())
989 {
990 return iz;
991 }
992 (*values)[i] = iz.isExpInitializer().exp;
993 assert(!(*values)[i].isErrorExp());
994 }
995 Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
996 auto ei = new ExpInitializer(init.loc, e);
997 return ei.inferType(sc);
998 }
999 else
1000 {
1001 auto elements = new Expressions(init.value.dim);
1002 elements.zero();
1003 for (size_t i = 0; i < init.value.dim; i++)
1004 {
1005 assert(!init.index[i]); // already asserted by isAssociativeArray()
1006 Initializer iz = init.value[i];
1007 if (!iz)
1008 goto Lno;
1009 iz = iz.inferType(sc);
1010 if (iz.isErrorInitializer())
1011 {
1012 return iz;
1013 }
1014 (*elements)[i] = iz.isExpInitializer().exp;
1015 assert(!(*elements)[i].isErrorExp());
1016 }
1017 Expression e = new ArrayLiteralExp(init.loc, null, elements);
1018 auto ei = new ExpInitializer(init.loc, e);
1019 return ei.inferType(sc);
1020 }
1021 Lno:
1022 if (keys)
1023 {
1024 error(init.loc, "not an associative array initializer");
1025 }
1026 else
1027 {
1028 error(init.loc, "cannot infer type from array initializer");
1029 }
1030 return new ErrorInitializer();
1031 }
1032
1033 Initializer visitExp(ExpInitializer init)
1034 {
1035 //printf("ExpInitializer::inferType() %s\n", init.toChars());
1036 init.exp = init.exp.expressionSemantic(sc);
1037
1038 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
1039 if (init.exp.op == EXP.type)
1040 init.exp = resolveAliasThis(sc, init.exp);
1041
1042 init.exp = resolveProperties(sc, init.exp);
1043 if (auto se = init.exp.isScopeExp())
1044 {
1045 TemplateInstance ti = se.sds.isTemplateInstance();
1046 if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
1047 se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
1048 else
1049 se.error("cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
1050 return new ErrorInitializer();
1051 }
1052
1053 // Give error for overloaded function addresses
1054 bool hasOverloads;
1055 if (auto f = isFuncAddress(init.exp, &hasOverloads))
1056 {
1057 if (f.checkForwardRef(init.loc))
1058 {
1059 return new ErrorInitializer();
1060 }
1061 if (hasOverloads && !f.isUnique())
1062 {
1063 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1064 return new ErrorInitializer();
1065 }
1066 }
1067 if (auto ae = init.exp.isAddrExp())
1068 {
1069 if (ae.e1.op == EXP.overloadSet)
1070 {
1071 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1072 return new ErrorInitializer();
1073 }
1074 }
1075 if (init.exp.isErrorExp())
1076 {
1077 return new ErrorInitializer();
1078 }
1079 if (!init.exp.type)
1080 {
1081 return new ErrorInitializer();
1082 }
1083 return init;
1084 }
1085
1086 Initializer visitC(CInitializer i)
1087 {
1088 //printf("CInitializer.inferType()\n");
1089 error(i.loc, "TODO C inferType initializers not supported yet");
1090 return new ErrorInitializer();
1091 }
1092
1093 final switch (init.kind)
1094 {
1095 case InitKind.void_: return visitVoid (init.isVoidInitializer());
1096 case InitKind.error: return visitError (init.isErrorInitializer());
1097 case InitKind.struct_: return visitStruct(init.isStructInitializer());
1098 case InitKind.array: return visitArray (init.isArrayInitializer());
1099 case InitKind.exp: return visitExp (init.isExpInitializer());
1100 case InitKind.C_: return visitC (init.isCInitializer());
1101 }
1102 }
1103
1104 /***********************
1105 * Translate init to an `Expression`.
1106 * Params:
1107 * init = `Initializer` AST node
1108 * itype = if not `null`, type to coerce expression to
1109 * isCfile = default initializers are different with C
1110 * Returns:
1111 * `Expression` created, `null` if cannot, `ErrorExp` for other errors
1112 */
1113 extern (C++) Expression initializerToExpression(Initializer init, Type itype = null, const bool isCfile = false)
1114 {
1115 //printf("initializerToExpression() isCfile: %d\n", isCfile);
1116
visitVoid(VoidInitializer)1117 Expression visitVoid(VoidInitializer)
1118 {
1119 return null;
1120 }
1121
visitError(ErrorInitializer)1122 Expression visitError(ErrorInitializer)
1123 {
1124 return ErrorExp.get();
1125 }
1126
1127 /***************************************
1128 * This works by transforming a struct initializer into
1129 * a struct literal. In the future, the two should be the
1130 * same thing.
1131 */
visitStruct(StructInitializer)1132 Expression visitStruct(StructInitializer)
1133 {
1134 // cannot convert to an expression without target 'ad'
1135 return null;
1136 }
1137
1138 /********************************
1139 * If possible, convert array initializer to array literal.
1140 * Otherwise return NULL.
1141 */
visitArray(ArrayInitializer init)1142 Expression visitArray(ArrayInitializer init)
1143 {
1144 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
1145 //static int i; if (++i == 2) assert(0);
1146 uint edim; // the length of the resulting array literal
1147 const(uint) amax = 0x80000000;
1148 Type t = null; // type of the array literal being initialized
1149 if (init.type)
1150 {
1151 if (init.type == Type.terror)
1152 {
1153 return ErrorExp.get();
1154 }
1155 t = init.type.toBasetype();
1156 switch (t.ty)
1157 {
1158 case Tvector:
1159 t = t.isTypeVector().basetype;
1160 goto case Tsarray;
1161
1162 case Tsarray:
1163 uinteger_t adim = t.isTypeSArray().dim.toInteger();
1164 if (adim >= amax)
1165 return null;
1166 edim = cast(uint)adim;
1167 break;
1168
1169 case Tpointer:
1170 case Tarray:
1171 edim = init.dim;
1172 break;
1173
1174 default:
1175 assert(0);
1176 }
1177 }
1178 else
1179 {
1180 /* Calculate the length of the array literal
1181 */
1182 edim = cast(uint)init.value.dim;
1183 size_t j = 0;
1184 foreach (i; 0 .. init.value.dim)
1185 {
1186 if (auto e = init.index[i])
1187 {
1188 if (e.op == EXP.int64)
1189 {
1190 const uinteger_t idxval = e.toInteger();
1191 if (idxval >= amax)
1192 return null;
1193 j = cast(size_t)idxval;
1194 }
1195 else
1196 return null;
1197 }
1198 ++j;
1199 if (j > edim)
1200 edim = cast(uint)j;
1201 }
1202 }
1203
1204 auto elements = new Expressions(edim);
1205 elements.zero();
1206 size_t j = 0;
1207 foreach (i; 0 .. init.value.dim)
1208 {
1209 if (auto e = init.index[i])
1210 j = cast(size_t)e.toInteger();
1211 assert(j < edim);
1212 if (Initializer iz = init.value[i])
1213 {
1214 if (Expression ex = iz.initializerToExpression(null, isCfile))
1215 {
1216 (*elements)[j] = ex;
1217 ++j;
1218 }
1219 else
1220 return null;
1221 }
1222 else
1223 return null;
1224 }
1225
1226 /* Fill in any missing elements with the default initializer
1227 */
1228 Expression defaultInit = null; // lazily create it
1229 foreach (ref element; (*elements)[0 .. edim])
1230 {
1231 if (!element)
1232 {
1233 if (!init.type) // don't know what type to use
1234 return null;
1235 if (!defaultInit)
1236 defaultInit = (cast(TypeNext)t).next.defaultInit(Loc.initial, isCfile);
1237 element = defaultInit;
1238 }
1239 }
1240
1241 /* Expand any static array initializers that are a single expression
1242 * into an array of them
1243 * e => [e, e, ..., e, e]
1244 */
1245 if (t)
1246 {
1247 Type tn = t.nextOf().toBasetype();
1248 if (tn.ty == Tsarray)
1249 {
1250 const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger();
1251 Type te = tn.nextOf().toBasetype();
1252 foreach (ref e; *elements)
1253 {
1254 if (te.equals(e.type))
1255 {
1256 auto elements2 = new Expressions(dim);
1257 foreach (ref e2; *elements2)
1258 e2 = e;
1259 e = new ArrayLiteralExp(e.loc, tn, elements2);
1260 }
1261 }
1262 }
1263 }
1264
1265 /* If any elements are errors, then the whole thing is an error
1266 */
1267 foreach (e; (*elements)[0 .. edim])
1268 {
1269 if (e.op == EXP.error)
1270 {
1271 return e;
1272 }
1273 }
1274
1275 Expression e = new ArrayLiteralExp(init.loc, init.type, elements);
1276 return e;
1277 }
1278
visitExp(ExpInitializer i)1279 Expression visitExp(ExpInitializer i)
1280 {
1281 if (itype)
1282 {
1283 //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
1284 Type tb = itype.toBasetype();
1285 Expression e = (i.exp.op == EXP.construct || i.exp.op == EXP.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
1286 if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
1287 {
1288 TypeSArray tsa = cast(TypeSArray)tb;
1289 size_t d = cast(size_t)tsa.dim.toInteger();
1290 auto elements = new Expressions(d);
1291 for (size_t j = 0; j < d; j++)
1292 (*elements)[j] = e;
1293 auto ae = new ArrayLiteralExp(e.loc, itype, elements);
1294 return ae;
1295 }
1296 }
1297 return i.exp;
1298 }
1299
visitC(CInitializer i)1300 Expression visitC(CInitializer i)
1301 {
1302 //printf("CInitializer.initializerToExpression(null, true)\n");
1303 return null;
1304 }
1305
1306 final switch (init.kind)
1307 {
1308 case InitKind.void_: return visitVoid (init.isVoidInitializer());
1309 case InitKind.error: return visitError (init.isErrorInitializer());
1310 case InitKind.struct_: return visitStruct(init.isStructInitializer());
1311 case InitKind.array: return visitArray (init.isArrayInitializer());
1312 case InitKind.exp: return visitExp (init.isExpInitializer());
1313 case InitKind.C_: return visitC (init.isCInitializer());
1314 }
1315 }
1316
1317
1318 /**************************************
1319 * Determine if expression has non-constant pointers, or more precisely,
1320 * a pointer that CTFE cannot handle.
1321 * Params:
1322 * e = expression to check
1323 * Returns:
1324 * true if it has non-constant pointers
1325 */
hasNonConstPointers(Expression e)1326 private bool hasNonConstPointers(Expression e)
1327 {
1328 static bool checkArray(Expressions* elems)
1329 {
1330 foreach (e; *elems)
1331 {
1332 if (e && hasNonConstPointers(e))
1333 return true;
1334 }
1335 return false;
1336 }
1337
1338 if (e.type.ty == Terror)
1339 return false;
1340 if (e.op == EXP.null_)
1341 return false;
1342 if (auto se = e.isStructLiteralExp())
1343 {
1344 return checkArray(se.elements);
1345 }
1346 if (auto ae = e.isArrayLiteralExp())
1347 {
1348 if (!ae.type.nextOf().hasPointers())
1349 return false;
1350 return checkArray(ae.elements);
1351 }
1352 if (auto ae = e.isAssocArrayLiteralExp())
1353 {
1354 if (ae.type.nextOf().hasPointers() && checkArray(ae.values))
1355 return true;
1356 if (ae.type.isTypeAArray().index.hasPointers())
1357 return checkArray(ae.keys);
1358 return false;
1359 }
1360 if (auto ae = e.isAddrExp())
1361 {
1362 if (ae.type.nextOf().isImmutable() || ae.type.nextOf().isConst())
1363 {
1364 return false;
1365 }
1366 if (auto se = ae.e1.isStructLiteralExp())
1367 {
1368 if (!(se.stageflags & stageSearchPointers))
1369 {
1370 const old = se.stageflags;
1371 se.stageflags |= stageSearchPointers;
1372 bool ret = checkArray(se.elements);
1373 se.stageflags = old;
1374 return ret;
1375 }
1376 else
1377 {
1378 return false;
1379 }
1380 }
1381 return true;
1382 }
1383 if (e.type.ty == Tpointer && !e.type.isPtrToFunction())
1384 {
1385 if (e.op == EXP.symbolOffset) // address of a global is OK
1386 return false;
1387 if (e.op == EXP.int64) // cast(void *)int is OK
1388 return false;
1389 if (e.op == EXP.string_) // "abc".ptr is OK
1390 return false;
1391 return true;
1392 }
1393 return false;
1394 }
1395