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