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