]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/d/dmd/initsem.d
d: Merge upstream dmd 3982604c5, druntime bc58b1e9, phobos 12329adb6.
[thirdparty/gcc.git] / gcc / d / dmd / initsem.d
CommitLineData
5fee5ec3
IB
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
12module dmd.initsem;
13
14import core.stdc.stdio;
15import core.checkedint;
16
17import dmd.aggregate;
18import dmd.aliasthis;
19import dmd.arraytypes;
20import dmd.astenums;
21import dmd.dcast;
22import dmd.declaration;
23import dmd.dscope;
24import dmd.dstruct;
25import dmd.dsymbol;
26import dmd.dtemplate;
27import dmd.errors;
28import dmd.expression;
29import dmd.expressionsem;
30import dmd.func;
31import dmd.globals;
32import dmd.id;
33import dmd.identifier;
0fb57034 34import dmd.importc;
5fee5ec3
IB
35import dmd.init;
36import dmd.mtype;
37import dmd.opover;
38import dmd.statement;
39import dmd.target;
40import dmd.tokens;
41import 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 */
53Expression 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;
77Lno:
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 */
96extern(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 }
0fb57034 180 if (j >= nfields)
5fee5ec3 181 {
0fb57034 182 error(i.value[j].loc, "too many initializers for `%s`", sd.toChars());
5fee5ec3
IB
183 return err();
184 }
185
186 VarDeclaration vd = sd.fields[fieldi];
187 if (elems[fieldi])
188 {
0fb57034 189 error(i.value[j].loc, "duplicate initializer for field `%s`", vd.toChars());
5fee5ec3 190 errors = true;
0fb57034
IB
191 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
192 ++fieldi;
5fee5ec3
IB
193 continue;
194 }
195
196 // Check for @safe violations
197 if (vd.type.hasPointers)
198 {
0fb57034 199 if ((!t.alignment.isDefault() && t.alignment.get() < target.ptrsize ||
5fee5ec3
IB
200 (vd.offset & (target.ptrsize - 1))) &&
201 sc.func && sc.func.setUnsafe())
202 {
0fb57034 203 error(i.value[j].loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
5fee5ec3
IB
204 sd.toChars(), vd.toChars());
205 errors = true;
0fb57034
IB
206 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
207 ++fieldi;
208 continue;
5fee5ec3
IB
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 {
0fb57034 217 error(elems[k].loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
5fee5ec3
IB
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();
9c7d5e88 228 if (ex.op == EXP.error)
5fee5ec3
IB
229 {
230 errors = true;
0fb57034
IB
231 elems[fieldi] = ErrorExp.get(); // for better diagnostics on multiple errors
232 ++fieldi;
5fee5ec3
IB
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 = (cast(TypeVector)t).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;
9c7d5e88 334 if (idx.op == EXP.error)
5fee5ec3
IB
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
9c7d5e88 347 if (ei && ei.exp.op == EXP.tuple)
5fee5ec3
IB
348 {
349 TupleExp te = cast(TupleExp)ei.exp;
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 }
0fb57034 374 if (auto tsa = t.isTypeSArray())
5fee5ec3 375 {
0fb57034
IB
376 uinteger_t edim = tsa.dim.toInteger();
377 if (i.dim > edim && !(tsa.isIncomplete() && (sc.flags & SCOPE.Cfile)))
5fee5ec3
IB
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();
9c7d5e88
IB
387 if (sz == SIZE_INVALID)
388 return err();
5fee5ec3
IB
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();
9c7d5e88 408 if (i.exp.op == EXP.error)
5fee5ec3
IB
409 return err();
410 uint olderrors = global.errors;
0fb57034
IB
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
5fee5ec3
IB
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.
0fb57034 428 if (i.exp.implicitConvTo(t) && !(sc.flags & SCOPE.Cfile))
5fee5ec3
IB
429 {
430 i.exp = i.exp.implicitCastTo(sc, t);
431 }
432 if (!global.gag && olderrors != global.errors)
433 {
434 return i;
435 }
0fb57034
IB
436 if (sc.flags & SCOPE.Cfile)
437 /* the interpreter turns (char*)"string" into &"string"[0] which then
438 * it cannot interpret. Resolve that case by doing optimize() first
439 */
440 i.exp = i.exp.optimize(WANTvalue);
5fee5ec3 441 i.exp = i.exp.ctfeInterpret();
9c7d5e88 442 if (i.exp.op == EXP.voidExpression)
5fee5ec3
IB
443 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
444 }
445 else
446 {
447 i.exp = i.exp.optimize(WANTvalue);
448 }
0fb57034 449
5fee5ec3
IB
450 if (!global.gag && olderrors != global.errors)
451 {
452 return i; // Failed, suppress duplicate error messages
453 }
454 if (i.exp.type.ty == Ttuple && (cast(TypeTuple)i.exp.type).arguments.dim == 0)
455 {
456 Type et = i.exp.type;
457 i.exp = new TupleExp(i.exp.loc, new Expressions());
458 i.exp.type = et;
459 }
9c7d5e88 460 if (i.exp.op == EXP.type)
5fee5ec3
IB
461 {
462 i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars());
463 return err();
464 }
465 // Make sure all pointers are constants
466 if (needInterpret && hasNonConstPointers(i.exp))
467 {
468 i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", currExp.toChars());
469 return err();
470 }
5fee5ec3 471 Type ti = i.exp.type.toBasetype();
9c7d5e88 472 if (i.exp.op == EXP.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
5fee5ec3
IB
473 {
474 return new ExpInitializer(i.loc, i.exp);
475 }
476 /* Look for case of initializing a static array with a too-short
477 * string literal, such as:
478 * char[5] foo = "abc";
479 * Allow this by doing an explicit cast, which will lengthen the string
480 * literal.
481 */
9c7d5e88 482 if (i.exp.op == EXP.string_ && tb.ty == Tsarray)
5fee5ec3
IB
483 {
484 StringExp se = cast(StringExp)i.exp;
485 Type typeb = se.type.toBasetype();
486 TY tynto = tb.nextOf().ty;
487 if (!se.committed &&
488 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
489 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
490 {
491 i.exp = se.castTo(sc, t);
492 goto L1;
493 }
494 }
5fee5ec3
IB
495 /* C11 6.7.9-14..15
496 * Initialize an array of unknown size with a string.
5fee5ec3
IB
497 * Change to static array of known size
498 */
0fb57034
IB
499 if (sc.flags & SCOPE.Cfile && i.exp.isStringExp() &&
500 tb.isTypeSArray() && tb.isTypeSArray().isIncomplete())
5fee5ec3
IB
501 {
502 StringExp se = i.exp.isStringExp();
503 auto ts = new TypeSArray(tb.nextOf(), new IntegerExp(Loc.initial, se.len + 1, Type.tsize_t));
504 t = typeSemantic(ts, Loc.initial, sc);
505 i.exp.type = t;
506 tx = t;
507 }
508
509 // Look for implicit constructor call
510 if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t))
511 {
512 StructDeclaration sd = (cast(TypeStruct)tb).sym;
513 if (sd.ctor)
514 {
515 // Rewrite as S().ctor(exp)
516 Expression e;
517 e = new StructLiteralExp(i.loc, sd, null);
518 e = new DotIdExp(i.loc, e, Id.ctor);
519 e = new CallExp(i.loc, e, i.exp);
520 e = e.expressionSemantic(sc);
521 if (needInterpret)
522 i.exp = e.ctfeInterpret();
523 else
524 i.exp = e.optimize(WANTvalue);
525 }
526 else if (search_function(sd, Id.call))
527 {
528 /* https://issues.dlang.org/show_bug.cgi?id=1547
529 *
530 * Look for static opCall
531 *
532 * Rewrite as:
533 * i.exp = typeof(sd).opCall(arguments)
534 */
535
536 Expression e = typeDotIdExp(i.loc, sd.type, Id.call);
537 e = new CallExp(i.loc, e, i.exp);
538 e = e.expressionSemantic(sc);
539 e = resolveProperties(sc, e);
540 if (needInterpret)
541 i.exp = e.ctfeInterpret();
542 else
543 i.exp = e.optimize(WANTvalue);
544 }
545 }
546 // Look for the case of statically initializing an array
547 // with a single member.
548 if (tb.ty == Tsarray && !tb.nextOf().equals(ti.toBasetype().nextOf()) && i.exp.implicitConvTo(tb.nextOf()))
549 {
550 /* If the variable is not actually used in compile time, array creation is
551 * redundant. So delay it until invocation of toExpression() or toDt().
552 */
553 t = tb.nextOf();
554 }
555 if (i.exp.implicitConvTo(t))
556 {
557 i.exp = i.exp.implicitCastTo(sc, t);
558 }
559 else
560 {
561 // Look for mismatch of compile-time known length to emit
562 // better diagnostic message, as same as AssignExp::semantic.
563 if (tb.ty == Tsarray && i.exp.implicitConvTo(tb.nextOf().arrayOf()) > MATCH.nomatch)
564 {
565 uinteger_t dim1 = (cast(TypeSArray)tb).dim.toInteger();
566 uinteger_t dim2 = dim1;
9c7d5e88 567 if (i.exp.op == EXP.arrayLiteral)
5fee5ec3
IB
568 {
569 ArrayLiteralExp ale = cast(ArrayLiteralExp)i.exp;
570 dim2 = ale.elements ? ale.elements.dim : 0;
571 }
9c7d5e88 572 else if (i.exp.op == EXP.slice)
5fee5ec3
IB
573 {
574 Type tx = toStaticArrayType(cast(SliceExp)i.exp);
575 if (tx)
576 dim2 = (cast(TypeSArray)tx).dim.toInteger();
577 }
578 if (dim1 != dim2)
579 {
580 i.exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
581 i.exp = ErrorExp.get();
582 }
583 }
584 i.exp = i.exp.implicitCastTo(sc, t);
585 }
586 L1:
9c7d5e88 587 if (i.exp.op == EXP.error)
5fee5ec3
IB
588 {
589 return i;
590 }
591 if (needInterpret)
592 i.exp = i.exp.ctfeInterpret();
593 else
594 i.exp = i.exp.optimize(WANTvalue);
595 //printf("-ExpInitializer::semantic(): "); i.exp.print();
596 return i;
597 }
598
599 Initializer visitC(CInitializer ci)
600 {
601 if (ci.sem) // if semantic() already run
602 return ci;
603 //printf("CInitializer::semantic() (%s) %s\n", t.toChars(), ci.toChars());
604 ci.sem = true;
605 t = t.toBasetype();
606 ci.type = t; // later passes will need this
607
608 auto dil = ci.initializerList[];
609 size_t i = 0; // index into dil[]
610 const uint amax = 0x8000_0000;
611 bool errors;
612
613 /* If `{ expression }` return the expression initializer
614 */
615 ExpInitializer isBraceExpression()
616 {
617 return (dil.length == 1 && !dil[0].designatorList)
618 ? dil[0].initializer.isExpInitializer()
619 : null;
620 }
621
622 /* Convert struct initializer into ExpInitializer
623 */
624 Initializer structs(TypeStruct ts)
625 {
626 //printf("structs %s\n", ts.toChars());
627 StructDeclaration sd = ts.sym;
628 sd.size(ci.loc);
629 if (sd.sizeok != Sizeok.done)
630 {
631 errors = true;
632 return err();
633 }
634 const nfields = sd.nonHiddenFields();
635 auto elements = new Expressions(nfields);
636 auto elems = (*elements)[];
637 foreach (ref elem; elems)
638 elem = null;
639
640 FieldLoop:
641 for (size_t fieldi = 0; fieldi < nfields; ++fieldi)
642 {
643 if (i == dil.length)
644 break;
645
646 auto di = dil[i];
647 if (di.designatorList)
648 {
649 error(ci.loc, "C designator-list not supported yet");
650 errors = true;
651 break;
652 }
653
654 VarDeclaration vd = sd.fields[fieldi];
655
656 // Check for overlapping initializations (can happen with unions)
657 foreach (k, v2; sd.fields[0 .. nfields])
658 {
659 if (vd.isOverlappedWith(v2) && elems[k])
660 {
661 continue FieldLoop; // skip it
662 }
663 }
664
665 ++i;
666
667 // Convert initializer to Expression `ex`
668 assert(sc);
669 auto tm = vd.type.addMod(ts.mod);
670 auto iz = di.initializer.initializerSemantic(sc, tm, needInterpret);
671 auto ex = iz.initializerToExpression();
9c7d5e88 672 if (ex.op == EXP.error)
5fee5ec3
IB
673 {
674 errors = true;
675 continue;
676 }
677
678 elems[fieldi] = ex;
679 }
680 if (errors)
681 return err();
682
683 // Make a StructLiteralExp out of elements[]
684 Type tx = ts;
685 auto sle = new StructLiteralExp(ci.loc, sd, elements, tx);
686 if (!sd.fill(ci.loc, elements, false))
687 return err();
688 sle.type = tx;
689 auto ie = new ExpInitializer(ci.loc, sle);
690 return ie.initializerSemantic(sc, tx, needInterpret);
691 }
692
693 if (auto ts = t.isTypeStruct())
694 {
695 auto ei = structs(ts);
696 if (errors)
697 return err();
698 if (i < dil.length)
699 {
700 error(ci.loc, "%d extra initializer(s) for `struct %s`", cast(int)(dil.length - i), ts.toChars());
701 return err();
702 }
703 return ei;
704 }
705
706 auto tsa = t.isTypeSArray();
0fb57034 707 if (!tsa)
5fee5ec3
IB
708 {
709 /* Not an array. See if it is `{ exp }` which can be
710 * converted to an ExpInitializer
711 */
712 if (ExpInitializer ei = isBraceExpression())
713 {
714 return ei.initializerSemantic(sc, t, needInterpret);
715 }
716
717 error(ci.loc, "C non-array initializer (%s) %s not supported yet", t.toChars(), ci.toChars());
718 return err();
719 }
720
721 /* If it's an array of integral being initialized by `{ string }`
722 * replace with `string`
723 */
724 auto tn = t.nextOf();
725 if (tn.isintegral())
726 {
727 if (ExpInitializer ei = isBraceExpression())
728 {
729 if (ei.exp.isStringExp())
730 return ei.initializerSemantic(sc, t, needInterpret);
731 }
732 }
733
734 /* Support recursion to handle un-braced array initializers
735 * Params:
736 * t = element type
737 * dim = max number of elements
738 * Returns:
739 * # of elements in array
740 */
741 size_t array(Type t, size_t dim)
742 {
743 //printf(" type %s i %d dim %d dil.length = %d\n", t.toChars(), cast(int)i, cast(int)dim, cast(int)dil.length);
744 auto tn = t.nextOf().toBasetype();
0fb57034
IB
745 auto tnsa = tn.isTypeSArray();
746 if (tnsa && tnsa.isIncomplete())
5fee5ec3
IB
747 {
748 // C11 6.2.5-20 "element type shall be complete whenever the array type is specified"
0fb57034 749 error(ci.loc, "incomplete element type `%s` not allowed", tnsa.toChars());
5fee5ec3
IB
750 errors = true;
751 return 1;
752 }
753 if (i == dil.length)
754 return 0;
755 size_t n;
5fee5ec3
IB
756 const nelems = tnsa ? cast(size_t)tnsa.dim.toInteger() : 0;
757
0fb57034
IB
758 /* Run initializerSemantic on a single element.
759 */
760 Initializer elem(Initializer ie)
761 {
762 ++i;
763 auto tnx = tn; // in case initializerSemantic tries to change it
764 ie = ie.initializerSemantic(sc, tnx, needInterpret);
765 if (ie.isErrorInitializer())
766 errors = true;
767 assert(tnx == tn); // sub-types should not be modified
768 return ie;
769 }
770
5fee5ec3
IB
771 foreach (j; 0 .. dim)
772 {
773 auto di = dil[i];
774 if (di.designatorList)
775 {
776 error(ci.loc, "C designator-list not supported yet");
777 errors = true;
778 break;
779 }
780 if (tnsa && di.initializer.isExpInitializer())
781 {
782 // no braces enclosing array initializer, so recurse
783 array(tnsa, nelems);
784 }
785 else if (auto tns = tn.isTypeStruct())
786 {
0fb57034
IB
787 if (di.initializer.isExpInitializer())
788 {
789 // no braces enclosing struct initializer
790 dil[n].initializer = structs(tns);
791 }
792 else
793 dil[n].initializer = elem(di.initializer);
5fee5ec3
IB
794 }
795 else
796 {
0fb57034 797 di.initializer = elem(di.initializer);
5fee5ec3
IB
798 }
799 ++n;
800 if (i == dil.length)
801 break;
802 }
803 //printf(" n: %d i: %d\n", cast(int)n, cast(int)i);
804 return n;
805 }
806
0fb57034
IB
807 size_t dim = tsa.isIncomplete() ? dil.length : cast(size_t)tsa.dim.toInteger();
808 auto newdim = array(t, dim);
5fee5ec3
IB
809
810 if (errors)
811 return err();
812
0fb57034 813 if (tsa.isIncomplete()) // array of unknown length
5fee5ec3
IB
814 {
815 // Change to array of known length
0fb57034 816 tsa = new TypeSArray(tn, new IntegerExp(Loc.initial, newdim, Type.tsize_t));
5fee5ec3
IB
817 tx = tsa; // rewrite caller's type
818 ci.type = tsa; // remember for later passes
819 }
820 const uinteger_t edim = tsa.dim.toInteger();
821 if (i < dil.length)
822 {
823 error(ci.loc, "%d extra initializer(s) for static array length of %d", cast(int)(dil.length - i), cast(int)edim);
824 return err();
825 }
826
827 const sz = tn.size(); // element size
9c7d5e88
IB
828 if (sz == SIZE_INVALID)
829 return err();
5fee5ec3
IB
830 bool overflow;
831 const max = mulu(edim, sz, overflow);
832 if (overflow || max >= amax)
833 {
834 error(ci.loc, "array dimension %llu exceeds max of %llu", ulong(edim), ulong(amax / sz));
835 return err();
836 }
837
0fb57034
IB
838 /* If an array of simple elements, replace with an ArrayInitializer
839 */
840 auto tnb = tn.toBasetype();
841 if (!(tnb.isTypeSArray() || tnb.isTypeStruct()))
842 {
843 auto ai = new ArrayInitializer(ci.loc);
844 ai.dim = cast(uint) dil.length;
845 ai.index.setDim(dil.length);
846 ai.value.setDim(dil.length);
847 foreach (const j; 0 .. dil.length)
848 {
849 ai.index[j] = null;
850 ai.value[j] = dil[j].initializer;
851 }
852 auto ty = tx;
853 return ai.initializerSemantic(sc, ty, needInterpret);
854 }
855
856 if (newdim < ci.initializerList.length && tnb.isTypeStruct())
857 {
858 // https://issues.dlang.org/show_bug.cgi?id=22375
859 // initializerList can be bigger than the number of actual elements
860 // to initialize for array of structs because it is not required
861 // for values to have proper bracing.
862 // i.e: These are all valid initializers for `struct{int a,b;}[3]`:
863 // {1,2,3,4}, {{1,2},3,4}, {1,2,{3,4}}, {{1,2},{3,4}}
864 // In all examples above, the new length of the initializer list
865 // has been shortened from four elements to two. This is important,
866 // because `dil` is written back to directly, making the lowered
867 // initializer `{{1,2},{3,4}}` and not `{{1,2},{3,4},3,4}`.
868 ci.initializerList.length = newdim;
869 }
870
5fee5ec3
IB
871 return ci;
872 }
873
874 final switch (init.kind)
875 {
876 case InitKind.void_: return visitVoid (cast( VoidInitializer)init);
877 case InitKind.error: return visitError (cast( ErrorInitializer)init);
878 case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
879 case InitKind.array: return visitArray (cast( ArrayInitializer)init);
880 case InitKind.exp: return visitExp (cast( ExpInitializer)init);
881 case InitKind.C_: return visitC (cast( CInitializer)init);
882 }
883}
884
885/***********************
886 * Translate init to an `Expression` in order to infer the type.
887 * Params:
888 * init = `Initializer` AST node
889 * sc = context
890 * Returns:
891 * an equivalent `ExpInitializer` if successful, or `ErrorInitializer` if it cannot be translated
892 */
893Initializer inferType(Initializer init, Scope* sc)
894{
895 Initializer visitVoid(VoidInitializer i)
896 {
897 error(i.loc, "cannot infer type from void initializer");
898 return new ErrorInitializer();
899 }
900
901 Initializer visitError(ErrorInitializer i)
902 {
903 return i;
904 }
905
906 Initializer visitStruct(StructInitializer i)
907 {
908 error(i.loc, "cannot infer type from struct initializer");
909 return new ErrorInitializer();
910 }
911
912 Initializer visitArray(ArrayInitializer init)
913 {
914 //printf("ArrayInitializer::inferType() %s\n", toChars());
915 Expressions* keys = null;
916 Expressions* values;
917 if (init.isAssociativeArray())
918 {
919 keys = new Expressions(init.value.dim);
920 values = new Expressions(init.value.dim);
921 for (size_t i = 0; i < init.value.dim; i++)
922 {
923 Expression e = init.index[i];
924 if (!e)
925 goto Lno;
926 (*keys)[i] = e;
927 Initializer iz = init.value[i];
928 if (!iz)
929 goto Lno;
930 iz = iz.inferType(sc);
931 if (iz.isErrorInitializer())
932 {
933 return iz;
934 }
935 assert(iz.isExpInitializer());
936 (*values)[i] = (cast(ExpInitializer)iz).exp;
9c7d5e88 937 assert(!(*values)[i].isErrorExp());
5fee5ec3
IB
938 }
939 Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
940 auto ei = new ExpInitializer(init.loc, e);
941 return ei.inferType(sc);
942 }
943 else
944 {
945 auto elements = new Expressions(init.value.dim);
946 elements.zero();
947 for (size_t i = 0; i < init.value.dim; i++)
948 {
949 assert(!init.index[i]); // already asserted by isAssociativeArray()
950 Initializer iz = init.value[i];
951 if (!iz)
952 goto Lno;
953 iz = iz.inferType(sc);
954 if (iz.isErrorInitializer())
955 {
956 return iz;
957 }
958 assert(iz.isExpInitializer());
959 (*elements)[i] = (cast(ExpInitializer)iz).exp;
9c7d5e88 960 assert(!(*elements)[i].isErrorExp());
5fee5ec3
IB
961 }
962 Expression e = new ArrayLiteralExp(init.loc, null, elements);
963 auto ei = new ExpInitializer(init.loc, e);
964 return ei.inferType(sc);
965 }
966 Lno:
967 if (keys)
968 {
969 error(init.loc, "not an associative array initializer");
970 }
971 else
972 {
973 error(init.loc, "cannot infer type from array initializer");
974 }
975 return new ErrorInitializer();
976 }
977
978 Initializer visitExp(ExpInitializer init)
979 {
980 //printf("ExpInitializer::inferType() %s\n", init.toChars());
981 init.exp = init.exp.expressionSemantic(sc);
982
983 // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
9c7d5e88 984 if (init.exp.op == EXP.type)
5fee5ec3
IB
985 init.exp = resolveAliasThis(sc, init.exp);
986
987 init.exp = resolveProperties(sc, init.exp);
9c7d5e88 988 if (init.exp.op == EXP.scope_)
5fee5ec3
IB
989 {
990 ScopeExp se = cast(ScopeExp)init.exp;
991 TemplateInstance ti = se.sds.isTemplateInstance();
992 if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
993 se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
994 else
995 se.error("cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
996 return new ErrorInitializer();
997 }
998
999 // Give error for overloaded function addresses
1000 bool hasOverloads;
1001 if (auto f = isFuncAddress(init.exp, &hasOverloads))
1002 {
1003 if (f.checkForwardRef(init.loc))
1004 {
1005 return new ErrorInitializer();
1006 }
1007 if (hasOverloads && !f.isUnique())
1008 {
1009 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1010 return new ErrorInitializer();
1011 }
1012 }
9c7d5e88 1013 if (init.exp.op == EXP.address)
5fee5ec3
IB
1014 {
1015 AddrExp ae = cast(AddrExp)init.exp;
9c7d5e88 1016 if (ae.e1.op == EXP.overloadSet)
5fee5ec3
IB
1017 {
1018 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
1019 return new ErrorInitializer();
1020 }
1021 }
9c7d5e88 1022 if (init.exp.op == EXP.error)
5fee5ec3
IB
1023 {
1024 return new ErrorInitializer();
1025 }
1026 if (!init.exp.type)
1027 {
1028 return new ErrorInitializer();
1029 }
1030 return init;
1031 }
1032
1033 Initializer visitC(CInitializer i)
1034 {
1035 //printf(CInitializer::inferType()\n");
1036 error(i.loc, "TODO C inferType initializers not supported yet");
1037 return new ErrorInitializer();
1038 }
1039
1040 final switch (init.kind)
1041 {
1042 case InitKind.void_: return visitVoid (cast( VoidInitializer)init);
1043 case InitKind.error: return visitError (cast( ErrorInitializer)init);
1044 case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
1045 case InitKind.array: return visitArray (cast( ArrayInitializer)init);
1046 case InitKind.exp: return visitExp (cast( ExpInitializer)init);
1047 case InitKind.C_: return visitC (cast( CInitializer)init);
1048 }
1049}
1050
1051/***********************
1052 * Translate init to an `Expression`.
1053 * Params:
1054 * init = `Initializer` AST node
1055 * itype = if not `null`, type to coerce expression to
1056 * Returns:
1057 * `Expression` created, `null` if cannot, `ErrorExp` for other errors
1058 */
1059extern (C++) Expression initializerToExpression(Initializer init, Type itype = null)
1060{
1061 Expression visitVoid(VoidInitializer)
1062 {
1063 return null;
1064 }
1065
1066 Expression visitError(ErrorInitializer)
1067 {
1068 return ErrorExp.get();
1069 }
1070
1071 /***************************************
1072 * This works by transforming a struct initializer into
1073 * a struct literal. In the future, the two should be the
1074 * same thing.
1075 */
1076 Expression visitStruct(StructInitializer)
1077 {
1078 // cannot convert to an expression without target 'ad'
1079 return null;
1080 }
1081
1082 /********************************
1083 * If possible, convert array initializer to array literal.
1084 * Otherwise return NULL.
1085 */
1086 Expression visitArray(ArrayInitializer init)
1087 {
1088 //printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
1089 //static int i; if (++i == 2) assert(0);
1090 uint edim; // the length of the resulting array literal
1091 const(uint) amax = 0x80000000;
1092 Type t = null; // type of the array literal being initialized
1093 if (init.type)
1094 {
1095 if (init.type == Type.terror)
1096 {
1097 return ErrorExp.get();
1098 }
1099 t = init.type.toBasetype();
1100 switch (t.ty)
1101 {
1102 case Tvector:
1103 t = t.isTypeVector().basetype;
1104 goto case Tsarray;
1105
1106 case Tsarray:
1107 uinteger_t adim = t.isTypeSArray().dim.toInteger();
1108 if (adim >= amax)
1109 return null;
1110 edim = cast(uint)adim;
1111 break;
1112
1113 case Tpointer:
1114 case Tarray:
1115 edim = init.dim;
1116 break;
1117
1118 default:
1119 assert(0);
1120 }
1121 }
1122 else
1123 {
1124 /* Calculate the length of the array literal
1125 */
1126 edim = cast(uint)init.value.dim;
1127 size_t j = 0;
1128 foreach (i; 0 .. init.value.dim)
1129 {
1130 if (auto e = init.index[i])
1131 {
9c7d5e88 1132 if (e.op == EXP.int64)
5fee5ec3
IB
1133 {
1134 const uinteger_t idxval = e.toInteger();
1135 if (idxval >= amax)
1136 return null;
1137 j = cast(size_t)idxval;
1138 }
1139 else
1140 return null;
1141 }
1142 ++j;
1143 if (j > edim)
1144 edim = cast(uint)j;
1145 }
1146 }
1147
1148 auto elements = new Expressions(edim);
1149 elements.zero();
1150 size_t j = 0;
1151 foreach (i; 0 .. init.value.dim)
1152 {
1153 if (auto e = init.index[i])
1154 j = cast(size_t)e.toInteger();
1155 assert(j < edim);
1156 if (Initializer iz = init.value[i])
1157 {
1158 if (Expression ex = iz.initializerToExpression())
1159 {
1160 (*elements)[j] = ex;
1161 ++j;
1162 }
1163 else
1164 return null;
1165 }
1166 else
1167 return null;
1168 }
1169
1170 /* Fill in any missing elements with the default initializer
1171 */
1172 Expression defaultInit = null; // lazily create it
1173 foreach (ref element; (*elements)[0 .. edim])
1174 {
1175 if (!element)
1176 {
1177 if (!init.type) // don't know what type to use
1178 return null;
1179 if (!defaultInit)
1180 defaultInit = (cast(TypeNext)t).next.defaultInit(Loc.initial);
1181 element = defaultInit;
1182 }
1183 }
1184
1185 /* Expand any static array initializers that are a single expression
1186 * into an array of them
1187 * e => [e, e, ..., e, e]
1188 */
1189 if (t)
1190 {
1191 Type tn = t.nextOf().toBasetype();
1192 if (tn.ty == Tsarray)
1193 {
1194 const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger();
1195 Type te = tn.nextOf().toBasetype();
1196 foreach (ref e; *elements)
1197 {
1198 if (te.equals(e.type))
1199 {
1200 auto elements2 = new Expressions(dim);
1201 foreach (ref e2; *elements2)
1202 e2 = e;
1203 e = new ArrayLiteralExp(e.loc, tn, elements2);
1204 }
1205 }
1206 }
1207 }
1208
1209 /* If any elements are errors, then the whole thing is an error
1210 */
1211 foreach (e; (*elements)[0 .. edim])
1212 {
9c7d5e88 1213 if (e.op == EXP.error)
5fee5ec3
IB
1214 {
1215 return e;
1216 }
1217 }
1218
1219 Expression e = new ArrayLiteralExp(init.loc, init.type, elements);
1220 return e;
1221 }
1222
1223 Expression visitExp(ExpInitializer i)
1224 {
1225 if (itype)
1226 {
1227 //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
1228 Type tb = itype.toBasetype();
9c7d5e88 1229 Expression e = (i.exp.op == EXP.construct || i.exp.op == EXP.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
5fee5ec3
IB
1230 if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
1231 {
1232 TypeSArray tsa = cast(TypeSArray)tb;
1233 size_t d = cast(size_t)tsa.dim.toInteger();
1234 auto elements = new Expressions(d);
1235 for (size_t j = 0; j < d; j++)
1236 (*elements)[j] = e;
1237 auto ae = new ArrayLiteralExp(e.loc, itype, elements);
1238 return ae;
1239 }
1240 }
1241 return i.exp;
1242 }
1243
1244 Expression visitC(CInitializer i)
1245 {
1246 //printf("CInitializer.initializerToExpression()\n");
1247 return null;
1248 }
1249
1250 final switch (init.kind)
1251 {
1252 case InitKind.void_: return visitVoid (cast( VoidInitializer)init);
1253 case InitKind.error: return visitError (cast( ErrorInitializer)init);
1254 case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
1255 case InitKind.array: return visitArray (cast( ArrayInitializer)init);
1256 case InitKind.exp: return visitExp (cast( ExpInitializer)init);
1257 case InitKind.C_: return visitC (cast( CInitializer)init);
1258 }
1259}
1260
1261
1262/**************************************
1263 * Determine if expression has non-constant pointers, or more precisely,
1264 * a pointer that CTFE cannot handle.
1265 * Params:
1266 * e = expression to check
1267 * Returns:
1268 * true if it has non-constant pointers
1269 */
1270private bool hasNonConstPointers(Expression e)
1271{
1272 static bool checkArray(Expressions* elems)
1273 {
1274 foreach (e; *elems)
1275 {
1276 if (e && hasNonConstPointers(e))
1277 return true;
1278 }
1279 return false;
1280 }
1281
1282 if (e.type.ty == Terror)
1283 return false;
9c7d5e88 1284 if (e.op == EXP.null_)
5fee5ec3
IB
1285 return false;
1286 if (auto se = e.isStructLiteralExp())
1287 {
1288 return checkArray(se.elements);
1289 }
1290 if (auto ae = e.isArrayLiteralExp())
1291 {
1292 if (!ae.type.nextOf().hasPointers())
1293 return false;
1294 return checkArray(ae.elements);
1295 }
1296 if (auto ae = e.isAssocArrayLiteralExp())
1297 {
1298 if (ae.type.nextOf().hasPointers() && checkArray(ae.values))
1299 return true;
1300 if ((cast(TypeAArray)ae.type).index.hasPointers())
1301 return checkArray(ae.keys);
1302 return false;
1303 }
1304 if (auto ae = e.isAddrExp())
1305 {
1306 if (auto se = ae.e1.isStructLiteralExp())
1307 {
1308 if (!(se.stageflags & stageSearchPointers))
1309 {
1310 const old = se.stageflags;
1311 se.stageflags |= stageSearchPointers;
1312 bool ret = checkArray(se.elements);
1313 se.stageflags = old;
1314 return ret;
1315 }
1316 else
1317 {
1318 return false;
1319 }
1320 }
1321 return true;
1322 }
1323 if (e.type.ty == Tpointer && !e.type.isPtrToFunction())
1324 {
9c7d5e88 1325 if (e.op == EXP.symbolOffset) // address of a global is OK
5fee5ec3 1326 return false;
9c7d5e88 1327 if (e.op == EXP.int64) // cast(void *)int is OK
5fee5ec3 1328 return false;
9c7d5e88 1329 if (e.op == EXP.string_) // "abc".ptr is OK
5fee5ec3
IB
1330 return false;
1331 return true;
1332 }
1333 return false;
1334}