xref: /netbsd/external/gpl3/gcc/dist/gcc/d/dmd/initsem.d (revision f0fbc68b)
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