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