1 /**
2  * Semantic analysis of initializers.
3  *
4  * Copyright:   Copyright (C) 1999-2020 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.dcast;
21 import dmd.declaration;
22 import dmd.dscope;
23 import dmd.dstruct;
24 import dmd.dsymbol;
25 import dmd.dtemplate;
26 import dmd.errors;
27 import dmd.expression;
28 import dmd.expressionsem;
29 import dmd.func;
30 import dmd.globals;
31 import dmd.id;
32 import dmd.identifier;
33 import dmd.init;
34 import dmd.mtype;
35 import dmd.opover;
36 import dmd.statement;
37 import dmd.target;
38 import dmd.tokens;
39 import dmd.typesem;
40 
41 /********************************
42  * If possible, convert array initializer to associative array initializer.
43  *
44  *  Params:
45  *     ai = array initializer to be converted
46  *
47  *  Returns:
48  *     The converted associative array initializer or ErrorExp if `ai`
49  *     is not an associative array initializer.
50  */
51 Expression toAssocArrayLiteral(ArrayInitializer ai)
52 {
53     Expression e;
54     //printf("ArrayInitializer::toAssocArrayInitializer()\n");
55     //static int i; if (++i == 2) assert(0);
56     const dim = ai.value.dim;
57     auto keys = new Expressions(dim);
58     auto values = new Expressions(dim);
59     for (size_t i = 0; i < dim; i++)
60     {
61         e = ai.index[i];
62         if (!e)
63             goto Lno;
64         (*keys)[i] = e;
65         Initializer iz = ai.value[i];
66         if (!iz)
67             goto Lno;
68         e = iz.initializerToExpression();
69         if (!e)
70             goto Lno;
71         (*values)[i] = e;
72     }
73     e = new AssocArrayLiteralExp(ai.loc, keys, values);
74     return e;
75 Lno:
76     error(ai.loc, "not an associative array initializer");
77     return new ErrorExp();
78 }
79 
80 /******************************************
81  * Perform semantic analysis on init.
82  * Params:
83  *      init = Initializer AST node
84  *      sc = context
85  *      t = type that the initializer needs to become
86  *      needInterpret = if CTFE needs to be run on this,
87  *                      such as if it is the initializer for a const declaration
88  * Returns:
89  *      `Initializer` with completed semantic analysis, `ErrorInitializer` if errors
90  *      were encountered
91  */
92 extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, Type t, NeedInterpret needInterpret)
93 {
94     Initializer visitVoid(VoidInitializer i)
95     {
96         i.type = t;
97         return i;
98     }
99 
100     Initializer visitError(ErrorInitializer i)
101     {
102         return i;
103     }
104 
105     Initializer visitStruct(StructInitializer i)
106     {
107         //printf("StructInitializer::semantic(t = %s) %s\n", t.toChars(), toChars());
108         t = t.toBasetype();
109         if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct)
110             t = t.nextOf().toBasetype();
111         if (t.ty == Tstruct)
112         {
113             StructDeclaration sd = (cast(TypeStruct)t).sym;
114             if (sd.ctor)
115             {
116                 error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars());
117                 return new ErrorInitializer();
118             }
119             sd.size(i.loc);
120             if (sd.sizeok != Sizeok.done)
121             {
122                 return new ErrorInitializer();
123             }
124             const nfields = sd.nonHiddenFields();
125             //expandTuples for non-identity arguments?
126             auto elements = new Expressions(nfields);
127             for (size_t j = 0; j < elements.dim; j++)
128                 (*elements)[j] = null;
129             // Run semantic for explicitly given initializers
130             // TODO: this part is slightly different from StructLiteralExp::semantic.
131             bool errors = false;
132             for (size_t fieldi = 0, j = 0; j < i.field.dim; j++)
133             {
134                 if (Identifier id = i.field[j])
135                 {
136                     Dsymbol s = sd.search(i.loc, id);
137                     if (!s)
138                     {
139                         s = sd.search_correct(id);
140                         Loc initLoc = i.value[j].loc;
141                         if (s)
142                             error(initLoc, "`%s` is not a member of `%s`, did you mean %s `%s`?", id.toChars(), sd.toChars(), s.kind(), s.toChars());
143                         else
144                             error(initLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars());
145                         return new ErrorInitializer();
146                     }
147                     s = s.toAlias();
148                     // Find out which field index it is
149                     for (fieldi = 0; 1; fieldi++)
150                     {
151                         if (fieldi >= nfields)
152                         {
153                             error(i.loc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars());
154                             return new ErrorInitializer();
155                         }
156                         if (s == sd.fields[fieldi])
157                             break;
158                     }
159                 }
160                 else if (fieldi >= nfields)
161                 {
162                     error(i.loc, "too many initializers for `%s`", sd.toChars());
163                     return new ErrorInitializer();
164                 }
165                 VarDeclaration vd = sd.fields[fieldi];
166                 if ((*elements)[fieldi])
167                 {
168                     error(i.loc, "duplicate initializer for field `%s`", vd.toChars());
169                     errors = true;
170                     continue;
171                 }
172                 if (vd.type.hasPointers)
173                 {
174                     if ((t.alignment() < target.ptrsize ||
175                          (vd.offset & (target.ptrsize - 1))) &&
176                         sc.func && sc.func.setUnsafe())
177                     {
178                         error(i.loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
179                             sd.toChars(), vd.toChars());
180                         errors = true;
181                     }
182                 }
183                 for (size_t k = 0; k < nfields; k++)
184                 {
185                     VarDeclaration v2 = sd.fields[k];
186                     if (vd.isOverlappedWith(v2) && (*elements)[k])
187                     {
188                         error(i.loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
189                         errors = true;
190                         continue;
191                     }
192                 }
193                 assert(sc);
194                 Initializer iz = i.value[j];
195                 iz = iz.initializerSemantic(sc, vd.type.addMod(t.mod), needInterpret);
196                 Expression ex = iz.initializerToExpression();
197                 if (ex.op == TOK.error)
198                 {
199                     errors = true;
200                     continue;
201                 }
202                 i.value[j] = iz;
203                 (*elements)[fieldi] = doCopyOrMove(sc, ex);
204                 ++fieldi;
205             }
206             if (errors)
207             {
208                 return new ErrorInitializer();
209             }
210             auto sle = new StructLiteralExp(i.loc, sd, elements, t);
211             if (!sd.fill(i.loc, elements, false))
212             {
213                 return new ErrorInitializer();
214             }
215             sle.type = t;
216             auto ie = new ExpInitializer(i.loc, sle);
217             return ie.initializerSemantic(sc, t, needInterpret);
218         }
219         else if ((t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction) && i.value.dim == 0)
220         {
221             TOK tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_;
222             /* Rewrite as empty delegate literal { }
223              */
224             Type tf = new TypeFunction(ParameterList(), null, LINK.d);
225             auto fd = new FuncLiteralDeclaration(i.loc, Loc.initial, tf, tok, null);
226             fd.fbody = new CompoundStatement(i.loc, new Statements());
227             fd.endloc = i.loc;
228             Expression e = new FuncExp(i.loc, fd);
229             auto ie = new ExpInitializer(i.loc, e);
230             return ie.initializerSemantic(sc, t, needInterpret);
231         }
232         if (t.ty != Terror)
233             error(i.loc, "a struct is not a valid initializer for a `%s`", t.toChars());
234         return new ErrorInitializer();
235     }
236 
237     Initializer visitArray(ArrayInitializer i)
238     {
239         uint length;
240         const(uint) amax = 0x80000000;
241         bool errors = false;
242         //printf("ArrayInitializer::semantic(%s)\n", t.toChars());
243         if (i.sem) // if semantic() already run
244         {
245             return i;
246         }
247         i.sem = true;
248         t = t.toBasetype();
249         switch (t.ty)
250         {
251         case Tsarray:
252         case Tarray:
253             break;
254         case Tvector:
255             t = (cast(TypeVector)t).basetype;
256             break;
257         case Taarray:
258         case Tstruct: // consider implicit constructor call
259             {
260                 Expression e;
261                 // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int])
262                 if (t.ty == Taarray || i.isAssociativeArray())
263                     e = i.toAssocArrayLiteral();
264                 else
265                     e = i.initializerToExpression();
266                 // Bugzilla 13987
267                 if (!e)
268                 {
269                     error(i.loc, "cannot use array to initialize `%s`", t.toChars());
270                     goto Lerr;
271                 }
272                 auto ei = new ExpInitializer(e.loc, e);
273                 return ei.initializerSemantic(sc, t, needInterpret);
274             }
275         case Tpointer:
276             if (t.nextOf().ty != Tfunction)
277                 break;
278             goto default;
279         default:
280             error(i.loc, "cannot use array to initialize `%s`", t.toChars());
281             goto Lerr;
282         }
283         i.type = t;
284         length = 0;
285         for (size_t j = 0; j < i.index.dim; j++)
286         {
287             Expression idx = i.index[j];
288             if (idx)
289             {
290                 sc = sc.startCTFE();
291                 idx = idx.expressionSemantic(sc);
292                 sc = sc.endCTFE();
293                 idx = idx.ctfeInterpret();
294                 i.index[j] = idx;
295                 const uinteger_t idxvalue = idx.toInteger();
296                 if (idxvalue >= amax)
297                 {
298                     error(i.loc, "array index %llu overflow", ulong(idxvalue));
299                     errors = true;
300                 }
301                 length = cast(uint)idxvalue;
302                 if (idx.op == TOK.error)
303                     errors = true;
304             }
305             Initializer val = i.value[j];
306             ExpInitializer ei = val.isExpInitializer();
307             if (ei && !idx)
308                 ei.expandTuples = true;
309             val = val.initializerSemantic(sc, t.nextOf(), needInterpret);
310             if (val.isErrorInitializer())
311                 errors = true;
312             ei = val.isExpInitializer();
313             // found a tuple, expand it
314             if (ei && ei.exp.op == TOK.tuple)
315             {
316                 TupleExp te = cast(TupleExp)ei.exp;
317                 i.index.remove(j);
318                 i.value.remove(j);
319                 for (size_t k = 0; k < te.exps.dim; ++k)
320                 {
321                     Expression e = (*te.exps)[k];
322                     i.index.insert(j + k, cast(Expression)null);
323                     i.value.insert(j + k, new ExpInitializer(e.loc, e));
324                 }
325                 j--;
326                 continue;
327             }
328             else
329             {
330                 i.value[j] = val;
331             }
332             length++;
333             if (length == 0)
334             {
335                 error(i.loc, "array dimension overflow");
336                 goto Lerr;
337             }
338             if (length > i.dim)
339                 i.dim = length;
340         }
341         if (t.ty == Tsarray)
342         {
343             uinteger_t edim = (cast(TypeSArray)t).dim.toInteger();
344             if (i.dim > edim)
345             {
346                 error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
347                 goto Lerr;
348             }
349         }
350         if (errors)
351             goto Lerr;
352         {
353             const sz = t.nextOf().size();
354             bool overflow;
355             const max = mulu(i.dim, sz, overflow);
356             if (overflow || max >= amax)
357             {
358                 error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz));
359                 goto Lerr;
360             }
361             return i;
362         }
363     Lerr:
364         return new ErrorInitializer();
365     }
366 
367     Initializer visitExp(ExpInitializer i)
368     {
369         //printf("ExpInitializer::semantic(%s), type = %s\n", i.exp.toChars(), t.toChars());
370         if (needInterpret)
371             sc = sc.startCTFE();
372         i.exp = i.exp.expressionSemantic(sc);
373         i.exp = resolveProperties(sc, i.exp);
374         if (needInterpret)
375             sc = sc.endCTFE();
376         if (i.exp.op == TOK.error)
377         {
378             return new ErrorInitializer();
379         }
380         uint olderrors = global.errors;
381         if (needInterpret)
382         {
383             // If the result will be implicitly cast, move the cast into CTFE
384             // to avoid premature truncation of polysemous types.
385             // eg real [] x = [1.1, 2.2]; should use real precision.
386             if (i.exp.implicitConvTo(t))
387             {
388                 i.exp = i.exp.implicitCastTo(sc, t);
389             }
390             if (!global.gag && olderrors != global.errors)
391             {
392                 return i;
393             }
394             i.exp = i.exp.ctfeInterpret();
395             if (i.exp.op == TOK.voidExpression)
396                 error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
397         }
398         else
399         {
400             i.exp = i.exp.optimize(WANTvalue);
401         }
402         if (!global.gag && olderrors != global.errors)
403         {
404             return i; // Failed, suppress duplicate error messages
405         }
406         if (i.exp.type.ty == Ttuple && (cast(TypeTuple)i.exp.type).arguments.dim == 0)
407         {
408             Type et = i.exp.type;
409             i.exp = new TupleExp(i.exp.loc, new Expressions());
410             i.exp.type = et;
411         }
412         if (i.exp.op == TOK.type)
413         {
414             i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars());
415             return new ErrorInitializer();
416         }
417         // Make sure all pointers are constants
418         if (needInterpret && hasNonConstPointers(i.exp))
419         {
420             i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", i.exp.toChars());
421             return new ErrorInitializer();
422         }
423         Type tb = t.toBasetype();
424         Type ti = i.exp.type.toBasetype();
425         if (i.exp.op == TOK.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
426         {
427             return new ExpInitializer(i.loc, i.exp);
428         }
429         /* Look for case of initializing a static array with a too-short
430          * string literal, such as:
431          *  char[5] foo = "abc";
432          * Allow this by doing an explicit cast, which will lengthen the string
433          * literal.
434          */
435         if (i.exp.op == TOK.string_ && tb.ty == Tsarray)
436         {
437             StringExp se = cast(StringExp)i.exp;
438             Type typeb = se.type.toBasetype();
439             TY tynto = tb.nextOf().ty;
440             if (!se.committed &&
441                 (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
442                 se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
443             {
444                 i.exp = se.castTo(sc, t);
445                 goto L1;
446             }
447         }
448         // Look for implicit constructor call
449         if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t))
450         {
451             StructDeclaration sd = (cast(TypeStruct)tb).sym;
452             if (sd.ctor)
453             {
454                 // Rewrite as S().ctor(exp)
455                 Expression e;
456                 e = new StructLiteralExp(i.loc, sd, null);
457                 e = new DotIdExp(i.loc, e, Id.ctor);
458                 e = new CallExp(i.loc, e, i.exp);
459                 e = e.expressionSemantic(sc);
460                 if (needInterpret)
461                     i.exp = e.ctfeInterpret();
462                 else
463                     i.exp = e.optimize(WANTvalue);
464             }
465             else if (search_function(sd, Id.call))
466             {
467                 /* https://issues.dlang.org/show_bug.cgi?id=1547
468                  *
469                  * Look for static opCall
470                  *
471                  * Rewrite as:
472                  *  i.exp = typeof(sd).opCall(arguments)
473                  */
474 
475                 Expression e = typeDotIdExp(i.loc, sd.type, Id.call);
476                 e = new CallExp(i.loc, e, i.exp);
477                 e = e.expressionSemantic(sc);
478                 e = resolveProperties(sc, e);
479                 if (needInterpret)
480                     i.exp = e.ctfeInterpret();
481                 else
482                     i.exp = e.optimize(WANTvalue);
483             }
484         }
485         // Look for the case of statically initializing an array
486         // with a single member.
487         if (tb.ty == Tsarray && !tb.nextOf().equals(ti.toBasetype().nextOf()) && i.exp.implicitConvTo(tb.nextOf()))
488         {
489             /* If the variable is not actually used in compile time, array creation is
490              * redundant. So delay it until invocation of toExpression() or toDt().
491              */
492             t = tb.nextOf();
493         }
494         if (i.exp.implicitConvTo(t))
495         {
496             i.exp = i.exp.implicitCastTo(sc, t);
497         }
498         else
499         {
500             // Look for mismatch of compile-time known length to emit
501             // better diagnostic message, as same as AssignExp::semantic.
502             if (tb.ty == Tsarray && i.exp.implicitConvTo(tb.nextOf().arrayOf()) > MATCH.nomatch)
503             {
504                 uinteger_t dim1 = (cast(TypeSArray)tb).dim.toInteger();
505                 uinteger_t dim2 = dim1;
506                 if (i.exp.op == TOK.arrayLiteral)
507                 {
508                     ArrayLiteralExp ale = cast(ArrayLiteralExp)i.exp;
509                     dim2 = ale.elements ? ale.elements.dim : 0;
510                 }
511                 else if (i.exp.op == TOK.slice)
512                 {
513                     Type tx = toStaticArrayType(cast(SliceExp)i.exp);
514                     if (tx)
515                         dim2 = (cast(TypeSArray)tx).dim.toInteger();
516                 }
517                 if (dim1 != dim2)
518                 {
519                     i.exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
520                     i.exp = new ErrorExp();
521                 }
522             }
523             i.exp = i.exp.implicitCastTo(sc, t);
524         }
525     L1:
526         if (i.exp.op == TOK.error)
527         {
528             return i;
529         }
530         if (needInterpret)
531             i.exp = i.exp.ctfeInterpret();
532         else
533             i.exp = i.exp.optimize(WANTvalue);
534         //printf("-ExpInitializer::semantic(): "); i.exp.print();
535         return i;
536     }
537 
538     final switch (init.kind)
539     {
540         case InitKind.void_:   return visitVoid  (cast(  VoidInitializer)init);
541         case InitKind.error:   return visitError (cast( ErrorInitializer)init);
542         case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
543         case InitKind.array:   return visitArray (cast( ArrayInitializer)init);
544         case InitKind.exp:     return visitExp   (cast(   ExpInitializer)init);
545     }
546 }
547 
548 /***********************
549  * Translate init to an `Expression` in order to infer the type.
550  * Params:
551  *      init = `Initializer` AST node
552  *      sc = context
553  * Returns:
554  *      an equivalent `ExpInitializer` if successful, or `ErrorInitializer` if it cannot be translated
555  */
556 Initializer inferType(Initializer init, Scope* sc)
557 {
558     Initializer visitVoid(VoidInitializer i)
559     {
560         error(i.loc, "cannot infer type from void initializer");
561         return new ErrorInitializer();
562     }
563 
564     Initializer visitError(ErrorInitializer i)
565     {
566         return i;
567     }
568 
569     Initializer visitStruct(StructInitializer i)
570     {
571         error(i.loc, "cannot infer type from struct initializer");
572         return new ErrorInitializer();
573     }
574 
575     Initializer visitArray(ArrayInitializer init)
576     {
577         //printf("ArrayInitializer::inferType() %s\n", toChars());
578         Expressions* keys = null;
579         Expressions* values;
580         if (init.isAssociativeArray())
581         {
582             keys = new Expressions(init.value.dim);
583             values = new Expressions(init.value.dim);
584             for (size_t i = 0; i < init.value.dim; i++)
585             {
586                 Expression e = init.index[i];
587                 if (!e)
588                     goto Lno;
589                 (*keys)[i] = e;
590                 Initializer iz = init.value[i];
591                 if (!iz)
592                     goto Lno;
593                 iz = iz.inferType(sc);
594                 if (iz.isErrorInitializer())
595                 {
596                     return iz;
597                 }
598                 assert(iz.isExpInitializer());
599                 (*values)[i] = (cast(ExpInitializer)iz).exp;
600                 assert((*values)[i].op != TOK.error);
601             }
602             Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
603             auto ei = new ExpInitializer(init.loc, e);
604             return ei.inferType(sc);
605         }
606         else
607         {
608             auto elements = new Expressions(init.value.dim);
609             elements.zero();
610             for (size_t i = 0; i < init.value.dim; i++)
611             {
612                 assert(!init.index[i]); // already asserted by isAssociativeArray()
613                 Initializer iz = init.value[i];
614                 if (!iz)
615                     goto Lno;
616                 iz = iz.inferType(sc);
617                 if (iz.isErrorInitializer())
618                 {
619                     return iz;
620                 }
621                 assert(iz.isExpInitializer());
622                 (*elements)[i] = (cast(ExpInitializer)iz).exp;
623                 assert((*elements)[i].op != TOK.error);
624             }
625             Expression e = new ArrayLiteralExp(init.loc, null, elements);
626             auto ei = new ExpInitializer(init.loc, e);
627             return ei.inferType(sc);
628         }
629     Lno:
630         if (keys)
631         {
632             error(init.loc, "not an associative array initializer");
633         }
634         else
635         {
636             error(init.loc, "cannot infer type from array initializer");
637         }
638         return new ErrorInitializer();
639     }
640 
641     Initializer visitExp(ExpInitializer init)
642     {
643         //printf("ExpInitializer::inferType() %s\n", init.toChars());
644         init.exp = init.exp.expressionSemantic(sc);
645 
646         // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
647         if (init.exp.op == TOK.type)
648             init.exp = resolveAliasThis(sc, init.exp);
649 
650         init.exp = resolveProperties(sc, init.exp);
651         if (init.exp.op == TOK.scope_)
652         {
653             ScopeExp se = cast(ScopeExp)init.exp;
654             TemplateInstance ti = se.sds.isTemplateInstance();
655             if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
656                 se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
657             else
658                 se.error("cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
659             return new ErrorInitializer();
660         }
661 
662         // Give error for overloaded function addresses
663         bool hasOverloads;
664         if (auto f = isFuncAddress(init.exp, &hasOverloads))
665         {
666             if (f.checkForwardRef(init.loc))
667             {
668                 return new ErrorInitializer();
669             }
670             if (hasOverloads && !f.isUnique())
671             {
672                 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
673                 return new ErrorInitializer();
674             }
675         }
676         if (init.exp.op == TOK.address)
677         {
678             AddrExp ae = cast(AddrExp)init.exp;
679             if (ae.e1.op == TOK.overloadSet)
680             {
681                 init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
682                 return new ErrorInitializer();
683             }
684         }
685         if (init.exp.op == TOK.error)
686         {
687             return new ErrorInitializer();
688         }
689         if (!init.exp.type)
690         {
691             return new ErrorInitializer();
692         }
693         return init;
694     }
695 
696     final switch (init.kind)
697     {
698         case InitKind.void_:   return visitVoid  (cast(  VoidInitializer)init);
699         case InitKind.error:   return visitError (cast( ErrorInitializer)init);
700         case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
701         case InitKind.array:   return visitArray (cast( ArrayInitializer)init);
702         case InitKind.exp:     return visitExp   (cast(   ExpInitializer)init);
703     }
704 }
705 
706 /***********************
707  * Translate init to an `Expression`.
708  * Params:
709  *      init = `Initializer` AST node
710  *      itype = if not `null`, type to coerce expression to
711  * Returns:
712  *      `Expression` created, `null` if cannot, `ErrorExp` for other errors
713  */
714 extern (C++) Expression initializerToExpression(Initializer init, Type itype = null)
715 {
716     Expression visitVoid(VoidInitializer)
717     {
718         return null;
719     }
720 
721     Expression visitError(ErrorInitializer)
722     {
723         return new ErrorExp();
724     }
725 
726     /***************************************
727      * This works by transforming a struct initializer into
728      * a struct literal. In the future, the two should be the
729      * same thing.
730      */
731     Expression visitStruct(StructInitializer)
732     {
733         // cannot convert to an expression without target 'ad'
734         return null;
735     }
736 
737     /********************************
738      * If possible, convert array initializer to array literal.
739      * Otherwise return NULL.
740      */
741     Expression visitArray(ArrayInitializer init)
742     {
743         //printf("ArrayInitializer::toExpression(), dim = %d\n", dim);
744         //static int i; if (++i == 2) assert(0);
745         Expressions* elements;
746         uint edim;
747         const(uint) amax = 0x80000000;
748         Type t = null;
749         if (init.type)
750         {
751             if (init.type == Type.terror)
752             {
753                 return new ErrorExp();
754             }
755             t = init.type.toBasetype();
756             switch (t.ty)
757             {
758             case Tvector:
759                 t = (cast(TypeVector)t).basetype;
760                 goto case Tsarray;
761 
762             case Tsarray:
763                 uinteger_t adim = (cast(TypeSArray)t).dim.toInteger();
764                 if (adim >= amax)
765                     goto Lno;
766                 edim = cast(uint)adim;
767                 break;
768 
769             case Tpointer:
770             case Tarray:
771                 edim = init.dim;
772                 break;
773 
774             default:
775                 assert(0);
776             }
777         }
778         else
779         {
780             edim = cast(uint)init.value.dim;
781             for (size_t i = 0, j = 0; i < init.value.dim; i++, j++)
782             {
783                 if (init.index[i])
784                 {
785                     if (init.index[i].op == TOK.int64)
786                     {
787                         const uinteger_t idxval = init.index[i].toInteger();
788                         if (idxval >= amax)
789                             goto Lno;
790                         j = cast(size_t)idxval;
791                     }
792                     else
793                         goto Lno;
794                 }
795                 if (j >= edim)
796                     edim = cast(uint)(j + 1);
797             }
798         }
799         elements = new Expressions(edim);
800         elements.zero();
801         for (size_t i = 0, j = 0; i < init.value.dim; i++, j++)
802         {
803             if (init.index[i])
804                 j = cast(size_t)init.index[i].toInteger();
805             assert(j < edim);
806             Initializer iz = init.value[i];
807             if (!iz)
808                 goto Lno;
809             Expression ex = iz.initializerToExpression();
810             if (!ex)
811             {
812                 goto Lno;
813             }
814             (*elements)[j] = ex;
815         }
816         {
817             /* Fill in any missing elements with the default initializer
818              */
819             Expression _init = null;
820             for (size_t i = 0; i < edim; i++)
821             {
822                 if (!(*elements)[i])
823                 {
824                     if (!init.type)
825                         goto Lno;
826                     if (!_init)
827                         _init = (cast(TypeNext)t).next.defaultInit(Loc.initial);
828                     (*elements)[i] = _init;
829                 }
830             }
831 
832             /* Expand any static array initializers that are a single expression
833              * into an array of them
834              */
835             if (t)
836             {
837                 Type tn = t.nextOf().toBasetype();
838                 if (tn.ty == Tsarray)
839                 {
840                     const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger();
841                     Type te = tn.nextOf().toBasetype();
842                     foreach (ref e; *elements)
843                     {
844                         if (te.equals(e.type))
845                         {
846                             auto elements2 = new Expressions(dim);
847                             foreach (ref e2; *elements2)
848                                 e2 = e;
849                             e = new ArrayLiteralExp(e.loc, tn, elements2);
850                         }
851                     }
852                 }
853             }
854 
855             /* If any elements are errors, then the whole thing is an error
856              */
857             for (size_t i = 0; i < edim; i++)
858             {
859                 Expression e = (*elements)[i];
860                 if (e.op == TOK.error)
861                 {
862                     return e;
863                 }
864             }
865 
866             Expression e = new ArrayLiteralExp(init.loc, init.type, elements);
867             return e;
868         }
869     Lno:
870         return null;
871     }
872 
873     Expression visitExp(ExpInitializer i)
874     {
875         if (itype)
876         {
877             //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
878             Type tb = itype.toBasetype();
879             Expression e = (i.exp.op == TOK.construct || i.exp.op == TOK.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
880             if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
881             {
882                 TypeSArray tsa = cast(TypeSArray)tb;
883                 size_t d = cast(size_t)tsa.dim.toInteger();
884                 auto elements = new Expressions(d);
885                 for (size_t j = 0; j < d; j++)
886                     (*elements)[j] = e;
887                 auto ae = new ArrayLiteralExp(e.loc, itype, elements);
888                 return ae;
889             }
890         }
891         return i.exp;
892     }
893 
894 
895     final switch (init.kind)
896     {
897         case InitKind.void_:   return visitVoid  (cast(  VoidInitializer)init);
898         case InitKind.error:   return visitError (cast( ErrorInitializer)init);
899         case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
900         case InitKind.array:   return visitArray (cast( ArrayInitializer)init);
901         case InitKind.exp:     return visitExp   (cast(   ExpInitializer)init);
902     }
903 }