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