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 1
    Expression e;
54
    //printf("ArrayInitializer::toAssocArrayInitializer()\n");
55
    //static int i; if (++i == 2) assert(0);
56 1
    const dim = ai.value.dim;
57 1
    auto keys = new Expressions(dim);
58 1
    auto values = new Expressions(dim);
59 1
    for (size_t i = 0; i < dim; i++)
60
    {
61 1
        e = ai.index[i];
62 1
        if (!e)
63 0
            goto Lno;
64 1
        (*keys)[i] = e;
65 1
        Initializer iz = ai.value[i];
66 1
        if (!iz)
67 0
            goto Lno;
68 1
        e = iz.initializerToExpression();
69 1
        if (!e)
70 0
            goto Lno;
71 1
        (*values)[i] = e;
72
    }
73 1
    e = new AssocArrayLiteralExp(ai.loc, keys, values);
74 1
    return e;
75
Lno:
76 0
    error(ai.loc, "not an associative array initializer");
77 0
    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 1
        i.type = t;
97 1
        return i;
98
    }
99

100
    Initializer visitError(ErrorInitializer i)
101
    {
102 1
        return i;
103
    }
104

105
    Initializer visitStruct(StructInitializer i)
106
    {
107
        //printf("StructInitializer::semantic(t = %s) %s\n", t.toChars(), i.toChars());
108 1
        t = t.toBasetype();
109 1
        if (t.ty == Tsarray && t.nextOf().toBasetype().ty == Tstruct)
110 1
            t = t.nextOf().toBasetype();
111 1
        if (t.ty == Tstruct)
112
        {
113 1
            StructDeclaration sd = (cast(TypeStruct)t).sym;
114 1
            if (sd.hasNonDisabledCtor())
115
            {
116 1
                error(i.loc, "%s `%s` has constructors, cannot use `{ initializers }`, use `%s( initializers )` instead", sd.kind(), sd.toChars(), sd.toChars());
117 1
                return new ErrorInitializer();
118
            }
119 1
            sd.size(i.loc);
120 1
            if (sd.sizeok != Sizeok.done)
121
            {
122 0
                return new ErrorInitializer();
123
            }
124 1
            const nfields = sd.nonHiddenFields();
125
            //expandTuples for non-identity arguments?
126 1
            auto elements = new Expressions(nfields);
127 1
            for (size_t j = 0; j < elements.dim; j++)
128 1
                (*elements)[j] = null;
129
            // Run semantic for explicitly given initializers
130
            // TODO: this part is slightly different from StructLiteralExp::semantic.
131 1
            bool errors = false;
132 1
            for (size_t fieldi = 0, j = 0; j < i.field.dim; j++)
133
            {
134 1
                if (Identifier id = i.field[j])
135
                {
136 1
                    Dsymbol s = sd.search(i.loc, id);
137 1
                    if (!s)
138
                    {
139 1
                        s = sd.search_correct(id);
140 1
                        Loc initLoc = i.value[j].loc;
141 1
                        if (s)
142 1
                            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 1
                            error(initLoc, "`%s` is not a member of `%s`", id.toChars(), sd.toChars());
145 1
                        return new ErrorInitializer();
146
                    }
147 1
                    s.checkDeprecated(i.loc, sc);
148

149 1
                    s = s.toAlias();
150
                    // Find out which field index it is
151 1
                    for (fieldi = 0; 1; fieldi++)
152
                    {
153 1
                        if (fieldi >= nfields)
154
                        {
155 0
                            error(i.loc, "`%s.%s` is not a per-instance initializable field", sd.toChars(), s.toChars());
156 0
                            return new ErrorInitializer();
157
                        }
158 1
                        if (s == sd.fields[fieldi])
159 1
                            break;
160
                    }
161
                }
162 1
                else if (fieldi >= nfields)
163
                {
164 1
                    error(i.loc, "too many initializers for `%s`", sd.toChars());
165 1
                    return new ErrorInitializer();
166
                }
167 1
                VarDeclaration vd = sd.fields[fieldi];
168 1
                if ((*elements)[fieldi])
169
                {
170 0
                    error(i.loc, "duplicate initializer for field `%s`", vd.toChars());
171 0
                    errors = true;
172 0
                    continue;
173
                }
174 1
                if (vd.type.hasPointers)
175
                {
176 1
                    if ((t.alignment() < target.ptrsize ||
177 1
                         (vd.offset & (target.ptrsize - 1))) &&
178 1
                        sc.func && sc.func.setUnsafe())
179
                    {
180 1
                        error(i.loc, "field `%s.%s` cannot assign to misaligned pointers in `@safe` code",
181
                            sd.toChars(), vd.toChars());
182 1
                        errors = true;
183
                    }
184
                }
185 1
                for (size_t k = 0; k < nfields; k++)
186
                {
187 1
                    VarDeclaration v2 = sd.fields[k];
188 1
                    if (vd.isOverlappedWith(v2) && (*elements)[k])
189
                    {
190 1
                        error(i.loc, "overlapping initialization for field `%s` and `%s`", v2.toChars(), vd.toChars());
191 1
                        errors = true;
192 1
                        continue;
193
                    }
194
                }
195 1
                assert(sc);
196 1
                Initializer iz = i.value[j];
197 1
                iz = iz.initializerSemantic(sc, vd.type.addMod(t.mod), needInterpret);
198 1
                Expression ex = iz.initializerToExpression();
199 1
                if (ex.op == TOK.error)
200
                {
201 1
                    errors = true;
202 1
                    continue;
203
                }
204 1
                i.value[j] = iz;
205 1
                (*elements)[fieldi] = doCopyOrMove(sc, ex);
206 1
                ++fieldi;
207
            }
208 1
            if (errors)
209
            {
210 1
                return new ErrorInitializer();
211
            }
212 1
            auto sle = new StructLiteralExp(i.loc, sd, elements, t);
213 1
            if (!sd.fill(i.loc, elements, false))
214
            {
215 0
                return new ErrorInitializer();
216
            }
217 1
            sle.type = t;
218 1
            auto ie = new ExpInitializer(i.loc, sle);
219 1
            return ie.initializerSemantic(sc, t, needInterpret);
220
        }
221 1
        else if ((t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction) && i.value.dim == 0)
222
        {
223 1
            TOK tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_;
224
            /* Rewrite as empty delegate literal { }
225
             */
226 1
            Type tf = new TypeFunction(ParameterList(), null, LINK.d);
227 1
            auto fd = new FuncLiteralDeclaration(i.loc, Loc.initial, tf, tok, null);
228 1
            fd.fbody = new CompoundStatement(i.loc, new Statements());
229 1
            fd.endloc = i.loc;
230 1
            Expression e = new FuncExp(i.loc, fd);
231 1
            auto ie = new ExpInitializer(i.loc, e);
232 1
            return ie.initializerSemantic(sc, t, needInterpret);
233
        }
234 1
        if (t.ty != Terror)
235 1
            error(i.loc, "a struct is not a valid initializer for a `%s`", t.toChars());
236 1
        return new ErrorInitializer();
237
    }
238

239
    Initializer visitArray(ArrayInitializer i)
240
    {
241 1
        uint length;
242 1
        const(uint) amax = 0x80000000;
243 1
        bool errors = false;
244
        //printf("ArrayInitializer::semantic(%s)\n", t.toChars());
245 1
        if (i.sem) // if semantic() already run
246
        {
247 1
            return i;
248
        }
249 1
        i.sem = true;
250 1
        t = t.toBasetype();
251 1
        switch (t.ty)
252
        {
253 1
        case Tsarray:
254 1
        case Tarray:
255 1
            break;
256 1
        case Tvector:
257 1
            t = (cast(TypeVector)t).basetype;
258 1
            break;
259 1
        case Taarray:
260 1
        case Tstruct: // consider implicit constructor call
261
            {
262 1
                Expression e;
263
                // note: MyStruct foo = [1:2, 3:4] is correct code if MyStruct has a this(int[int])
264 1
                if (t.ty == Taarray || i.isAssociativeArray())
265 1
                    e = i.toAssocArrayLiteral();
266
                else
267 1
                    e = i.initializerToExpression();
268
                // Bugzilla 13987
269 1
                if (!e)
270
                {
271 1
                    error(i.loc, "cannot use array to initialize `%s`", t.toChars());
272 1
                    goto Lerr;
273
                }
274 1
                auto ei = new ExpInitializer(e.loc, e);
275 1
                return ei.initializerSemantic(sc, t, needInterpret);
276
            }
277 1
        case Tpointer:
278 1
            if (t.nextOf().ty != Tfunction)
279 1
                break;
280 1
            goto default;
281 1
        default:
282 1
            error(i.loc, "cannot use array to initialize `%s`", t.toChars());
283 1
            goto Lerr;
284
        }
285 1
        i.type = t;
286 1
        length = 0;
287 1
        for (size_t j = 0; j < i.index.dim; j++)
288
        {
289 1
            Expression idx = i.index[j];
290 1
            if (idx)
291
            {
292 1
                sc = sc.startCTFE();
293 1
                idx = idx.expressionSemantic(sc);
294 1
                sc = sc.endCTFE();
295 1
                idx = idx.ctfeInterpret();
296 1
                i.index[j] = idx;
297 1
                const uinteger_t idxvalue = idx.toInteger();
298 1
                if (idxvalue >= amax)
299
                {
300 1
                    error(i.loc, "array index %llu overflow", idxvalue);
301 1
                    errors = true;
302
                }
303 1
                length = cast(uint)idxvalue;
304 1
                if (idx.op == TOK.error)
305 0
                    errors = true;
306
            }
307 1
            Initializer val = i.value[j];
308 1
            ExpInitializer ei = val.isExpInitializer();
309 1
            if (ei && !idx)
310 1
                ei.expandTuples = true;
311 1
            val = val.initializerSemantic(sc, t.nextOf(), needInterpret);
312 1
            if (val.isErrorInitializer())
313 0
                errors = true;
314 1
            ei = val.isExpInitializer();
315
            // found a tuple, expand it
316 1
            if (ei && ei.exp.op == TOK.tuple)
317
            {
318 1
                TupleExp te = cast(TupleExp)ei.exp;
319 1
                i.index.remove(j);
320 1
                i.value.remove(j);
321 1
                for (size_t k = 0; k < te.exps.dim; ++k)
322
                {
323 1
                    Expression e = (*te.exps)[k];
324 1
                    i.index.insert(j + k, cast(Expression)null);
325 1
                    i.value.insert(j + k, new ExpInitializer(e.loc, e));
326
                }
327 1
                j--;
328 1
                continue;
329
            }
330
            else
331
            {
332 1
                i.value[j] = val;
333
            }
334 1
            length++;
335 1
            if (length == 0)
336
            {
337 1
                error(i.loc, "array dimension overflow");
338 1
                goto Lerr;
339
            }
340 1
            if (length > i.dim)
341 1
                i.dim = length;
342
        }
343 1
        if (t.ty == Tsarray)
344
        {
345 1
            uinteger_t edim = (cast(TypeSArray)t).dim.toInteger();
346 1
            if (i.dim > edim)
347
            {
348 0
                error(i.loc, "array initializer has %u elements, but array length is %llu", i.dim, edim);
349 0
                goto Lerr;
350
            }
351
        }
352 1
        if (errors)
353 0
            goto Lerr;
354
        {
355 1
            const sz = t.nextOf().size();
356 1
            bool overflow;
357 1
            const max = mulu(i.dim, sz, overflow);
358 1
            if (overflow || max >= amax)
359
            {
360 0
                error(i.loc, "array dimension %llu exceeds max of %llu", ulong(i.dim), ulong(amax / sz));
361 0
                goto Lerr;
362
            }
363 1
            return i;
364
        }
365
    Lerr:
366 1
        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 1
        if (needInterpret)
373 1
            sc = sc.startCTFE();
374 1
        i.exp = i.exp.expressionSemantic(sc);
375 1
        i.exp = resolveProperties(sc, i.exp);
376 1
        if (needInterpret)
377 1
            sc = sc.endCTFE();
378 1
        if (i.exp.op == TOK.error)
379
        {
380 1
            return new ErrorInitializer();
381
        }
382 1
        uint olderrors = global.errors;
383 1
        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 1
            if (i.exp.implicitConvTo(t))
389
            {
390 1
                i.exp = i.exp.implicitCastTo(sc, t);
391
            }
392 1
            if (!global.gag && olderrors != global.errors)
393
            {
394 1
                return i;
395
            }
396 1
            i.exp = i.exp.ctfeInterpret();
397 1
            if (i.exp.op == TOK.voidExpression)
398 1
                error(i.loc, "variables cannot be initialized with an expression of type `void`. Use `void` initialization instead.");
399
        }
400
        else
401
        {
402 1
            i.exp = i.exp.optimize(WANTvalue);
403
        }
404 1
        if (!global.gag && olderrors != global.errors)
405
        {
406 1
            return i; // Failed, suppress duplicate error messages
407
        }
408 1
        if (i.exp.type.ty == Ttuple && (cast(TypeTuple)i.exp.type).arguments.dim == 0)
409
        {
410 1
            Type et = i.exp.type;
411 1
            i.exp = new TupleExp(i.exp.loc, new Expressions());
412 1
            i.exp.type = et;
413
        }
414 1
        if (i.exp.op == TOK.type)
415
        {
416 1
            i.exp.error("initializer must be an expression, not `%s`", i.exp.toChars());
417 1
            return new ErrorInitializer();
418
        }
419
        // Make sure all pointers are constants
420 1
        if (needInterpret && hasNonConstPointers(i.exp))
421
        {
422 1
            i.exp.error("cannot use non-constant CTFE pointer in an initializer `%s`", i.exp.toChars());
423 1
            return new ErrorInitializer();
424
        }
425 1
        Type tb = t.toBasetype();
426 1
        Type ti = i.exp.type.toBasetype();
427 1
        if (i.exp.op == TOK.tuple && i.expandTuples && !i.exp.implicitConvTo(t))
428
        {
429 1
            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 1
        if (i.exp.op == TOK.string_ && tb.ty == Tsarray)
438
        {
439 1
            StringExp se = cast(StringExp)i.exp;
440 1
            Type typeb = se.type.toBasetype();
441 1
            TY tynto = tb.nextOf().ty;
442 1
            if (!se.committed &&
443 1
                (typeb.ty == Tarray || typeb.ty == Tsarray) && tynto.isSomeChar &&
444 1
                se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
445
            {
446 0
                i.exp = se.castTo(sc, t);
447 0
                goto L1;
448
            }
449
        }
450
        // Look for implicit constructor call
451 1
        if (tb.ty == Tstruct && !(ti.ty == Tstruct && tb.toDsymbol(sc) == ti.toDsymbol(sc)) && !i.exp.implicitConvTo(t))
452
        {
453 1
            StructDeclaration sd = (cast(TypeStruct)tb).sym;
454 1
            if (sd.ctor)
455
            {
456
                // Rewrite as S().ctor(exp)
457 1
                Expression e;
458 1
                e = new StructLiteralExp(i.loc, sd, null);
459 1
                e = new DotIdExp(i.loc, e, Id.ctor);
460 1
                e = new CallExp(i.loc, e, i.exp);
461 1
                e = e.expressionSemantic(sc);
462 1
                if (needInterpret)
463 1
                    i.exp = e.ctfeInterpret();
464
                else
465 1
                    i.exp = e.optimize(WANTvalue);
466
            }
467 1
            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 1
                Expression e = typeDotIdExp(i.loc, sd.type, Id.call);
478 1
                e = new CallExp(i.loc, e, i.exp);
479 1
                e = e.expressionSemantic(sc);
480 1
                e = resolveProperties(sc, e);
481 1
                if (needInterpret)
482 0
                    i.exp = e.ctfeInterpret();
483
                else
484 1
                    i.exp = e.optimize(WANTvalue);
485
            }
486
        }
487
        // Look for the case of statically initializing an array
488
        // with a single member.
489 1
        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 1
            t = tb.nextOf();
495
        }
496 1
        if (i.exp.implicitConvTo(t))
497
        {
498 1
            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 1
            if (tb.ty == Tsarray && i.exp.implicitConvTo(tb.nextOf().arrayOf()) > MATCH.nomatch)
505
            {
506 1
                uinteger_t dim1 = (cast(TypeSArray)tb).dim.toInteger();
507 1
                uinteger_t dim2 = dim1;
508 1
                if (i.exp.op == TOK.arrayLiteral)
509
                {
510 1
                    ArrayLiteralExp ale = cast(ArrayLiteralExp)i.exp;
511 1
                    dim2 = ale.elements ? ale.elements.dim : 0;
512
                }
513 0
                else if (i.exp.op == TOK.slice)
514
                {
515 0
                    Type tx = toStaticArrayType(cast(SliceExp)i.exp);
516 0
                    if (tx)
517 0
                        dim2 = (cast(TypeSArray)tx).dim.toInteger();
518
                }
519 1
                if (dim1 != dim2)
520
                {
521 1
                    i.exp.error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
522 1
                    i.exp = ErrorExp.get();
523
                }
524
            }
525 1
            i.exp = i.exp.implicitCastTo(sc, t);
526
        }
527
    L1:
528 1
        if (i.exp.op == TOK.error)
529
        {
530 1
            return i;
531
        }
532 1
        if (needInterpret)
533 1
            i.exp = i.exp.ctfeInterpret();
534
        else
535 1
            i.exp = i.exp.optimize(WANTvalue);
536
        //printf("-ExpInitializer::semantic(): "); i.exp.print();
537 1
        return i;
538
    }
539

540 1
    final switch (init.kind)
541
    {
542 1
        case InitKind.void_:   return visitVoid  (cast(  VoidInitializer)init);
543 1
        case InitKind.error:   return visitError (cast( ErrorInitializer)init);
544 1
        case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
545 1
        case InitKind.array:   return visitArray (cast( ArrayInitializer)init);
546 1
        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 0
        error(i.loc, "cannot infer type from void initializer");
563 0
        return new ErrorInitializer();
564
    }
565

566
    Initializer visitError(ErrorInitializer i)
567
    {
568 0
        return i;
569
    }
570

571
    Initializer visitStruct(StructInitializer i)
572
    {
573 0
        error(i.loc, "cannot infer type from struct initializer");
574 0
        return new ErrorInitializer();
575
    }
576

577
    Initializer visitArray(ArrayInitializer init)
578
    {
579
        //printf("ArrayInitializer::inferType() %s\n", toChars());
580 1
        Expressions* keys = null;
581 1
        Expressions* values;
582 1
        if (init.isAssociativeArray())
583
        {
584 1
            keys = new Expressions(init.value.dim);
585 1
            values = new Expressions(init.value.dim);
586 1
            for (size_t i = 0; i < init.value.dim; i++)
587
            {
588 1
                Expression e = init.index[i];
589 1
                if (!e)
590 0
                    goto Lno;
591 1
                (*keys)[i] = e;
592 1
                Initializer iz = init.value[i];
593 1
                if (!iz)
594 0
                    goto Lno;
595 1
                iz = iz.inferType(sc);
596 1
                if (iz.isErrorInitializer())
597
                {
598 0
                    return iz;
599
                }
600 1
                assert(iz.isExpInitializer());
601 1
                (*values)[i] = (cast(ExpInitializer)iz).exp;
602 1
                assert((*values)[i].op != TOK.error);
603
            }
604 1
            Expression e = new AssocArrayLiteralExp(init.loc, keys, values);
605 1
            auto ei = new ExpInitializer(init.loc, e);
606 1
            return ei.inferType(sc);
607
        }
608
        else
609
        {
610 1
            auto elements = new Expressions(init.value.dim);
611 1
            elements.zero();
612 1
            for (size_t i = 0; i < init.value.dim; i++)
613
            {
614 1
                assert(!init.index[i]); // already asserted by isAssociativeArray()
615 1
                Initializer iz = init.value[i];
616 1
                if (!iz)
617 0
                    goto Lno;
618 1
                iz = iz.inferType(sc);
619 1
                if (iz.isErrorInitializer())
620
                {
621 1
                    return iz;
622
                }
623 1
                assert(iz.isExpInitializer());
624 1
                (*elements)[i] = (cast(ExpInitializer)iz).exp;
625 1
                assert((*elements)[i].op != TOK.error);
626
            }
627 1
            Expression e = new ArrayLiteralExp(init.loc, null, elements);
628 1
            auto ei = new ExpInitializer(init.loc, e);
629 1
            return ei.inferType(sc);
630
        }
631
    Lno:
632 0
        if (keys)
633
        {
634 0
            error(init.loc, "not an associative array initializer");
635
        }
636
        else
637
        {
638 0
            error(init.loc, "cannot infer type from array initializer");
639
        }
640 0
        return new ErrorInitializer();
641
    }
642

643
    Initializer visitExp(ExpInitializer init)
644
    {
645
        //printf("ExpInitializer::inferType() %s\n", init.toChars());
646 1
        init.exp = init.exp.expressionSemantic(sc);
647

648
        // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684
649 1
        if (init.exp.op == TOK.type)
650 1
            init.exp = resolveAliasThis(sc, init.exp);
651

652 1
        init.exp = resolveProperties(sc, init.exp);
653 1
        if (init.exp.op == TOK.scope_)
654
        {
655 1
            ScopeExp se = cast(ScopeExp)init.exp;
656 1
            TemplateInstance ti = se.sds.isTemplateInstance();
657 1
            if (ti && ti.semanticRun == PASS.semantic && !ti.aliasdecl)
658 0
                se.error("cannot infer type from %s `%s`, possible circular dependency", se.sds.kind(), se.toChars());
659
            else
660 1
                se.error("cannot infer type from %s `%s`", se.sds.kind(), se.toChars());
661 1
            return new ErrorInitializer();
662
        }
663

664
        // Give error for overloaded function addresses
665 1
        bool hasOverloads;
666 1
        if (auto f = isFuncAddress(init.exp, &hasOverloads))
667
        {
668 1
            if (f.checkForwardRef(init.loc))
669
            {
670 1
                return new ErrorInitializer();
671
            }
672 1
            if (hasOverloads && !f.isUnique())
673
            {
674 1
                init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
675 1
                return new ErrorInitializer();
676
            }
677
        }
678 1
        if (init.exp.op == TOK.address)
679
        {
680 1
            AddrExp ae = cast(AddrExp)init.exp;
681 1
            if (ae.e1.op == TOK.overloadSet)
682
            {
683 1
                init.exp.error("cannot infer type from overloaded function symbol `%s`", init.exp.toChars());
684 1
                return new ErrorInitializer();
685
            }
686
        }
687 1
        if (init.exp.op == TOK.error)
688
        {
689 1
            return new ErrorInitializer();
690
        }
691 1
        if (!init.exp.type)
692
        {
693 0
            return new ErrorInitializer();
694
        }
695 1
        return init;
696
    }
697

698 1
    final switch (init.kind)
699
    {
700 0
        case InitKind.void_:   return visitVoid  (cast(  VoidInitializer)init);
701 0
        case InitKind.error:   return visitError (cast( ErrorInitializer)init);
702 0
        case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
703 1
        case InitKind.array:   return visitArray (cast( ArrayInitializer)init);
704 1
        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 1
        return null;
721
    }
722

723
    Expression visitError(ErrorInitializer)
724
    {
725 1
        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 1
        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 1
        Expressions* elements;
748 1
        uint edim;
749 1
        const(uint) amax = 0x80000000;
750 1
        Type t = null;
751 1
        if (init.type)
752
        {
753 1
            if (init.type == Type.terror)
754
            {
755 0
                return ErrorExp.get();
756
            }
757 1
            t = init.type.toBasetype();
758 1
            switch (t.ty)
759
            {
760 0
            case Tvector:
761 0
                t = (cast(TypeVector)t).basetype;
762 0
                goto case Tsarray;
763

764 1
            case Tsarray:
765 1
                uinteger_t adim = (cast(TypeSArray)t).dim.toInteger();
766 1
                if (adim >= amax)
767 0
                    goto Lno;
768 1
                edim = cast(uint)adim;
769 1
                break;
770

771 0
            case Tpointer:
772 1
            case Tarray:
773 1
                edim = init.dim;
774 1
                break;
775

776 0
            default:
777 0
                assert(0);
778
            }
779
        }
780
        else
781
        {
782 1
            edim = cast(uint)init.value.dim;
783 1
            for (size_t i = 0, j = 0; i < init.value.dim; i++, j++)
784
            {
785 1
                if (init.index[i])
786
                {
787 1
                    if (init.index[i].op == TOK.int64)
788
                    {
789 1
                        const uinteger_t idxval = init.index[i].toInteger();
790 1
                        if (idxval >= amax)
791 0
                            goto Lno;
792 1
                        j = cast(size_t)idxval;
793
                    }
794
                    else
795 1
                        goto Lno;
796
                }
797 1
                if (j >= edim)
798 1
                    edim = cast(uint)(j + 1);
799
            }
800
        }
801 1
        elements = new Expressions(edim);
802 1
        elements.zero();
803 1
        for (size_t i = 0, j = 0; i < init.value.dim; i++, j++)
804
        {
805 1
            if (init.index[i])
806 1
                j = cast(size_t)init.index[i].toInteger();
807 1
            assert(j < edim);
808 1
            Initializer iz = init.value[i];
809 1
            if (!iz)
810 0
                goto Lno;
811 1
            Expression ex = iz.initializerToExpression();
812 1
            if (!ex)
813
            {
814 1
                goto Lno;
815
            }
816 1
            (*elements)[j] = ex;
817
        }
818
        {
819
            /* Fill in any missing elements with the default initializer
820
             */
821 1
            Expression _init = null;
822 1
            for (size_t i = 0; i < edim; i++)
823
            {
824 1
                if (!(*elements)[i])
825
                {
826 1
                    if (!init.type)
827 1
                        goto Lno;
828 1
                    if (!_init)
829 1
                        _init = (cast(TypeNext)t).next.defaultInit(Loc.initial);
830 1
                    (*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 1
            if (t)
838
            {
839 1
                Type tn = t.nextOf().toBasetype();
840 1
                if (tn.ty == Tsarray)
841
                {
842 1
                    const dim = cast(size_t)(cast(TypeSArray)tn).dim.toInteger();
843 1
                    Type te = tn.nextOf().toBasetype();
844 1
                    foreach (ref e; *elements)
845
                    {
846 1
                        if (te.equals(e.type))
847
                        {
848 1
                            auto elements2 = new Expressions(dim);
849 1
                            foreach (ref e2; *elements2)
850 1
                                e2 = e;
851 1
                            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 1
            for (size_t i = 0; i < edim; i++)
860
            {
861 1
                Expression e = (*elements)[i];
862 1
                if (e.op == TOK.error)
863
                {
864 1
                    return e;
865
                }
866
            }
867

868 1
            Expression e = new ArrayLiteralExp(init.loc, init.type, elements);
869 1
            return e;
870
        }
871
    Lno:
872 1
        return null;
873
    }
874

875
    Expression visitExp(ExpInitializer i)
876
    {
877 1
        if (itype)
878
        {
879
            //printf("ExpInitializer::toExpression(t = %s) exp = %s\n", itype.toChars(), i.exp.toChars());
880 1
            Type tb = itype.toBasetype();
881 1
            Expression e = (i.exp.op == TOK.construct || i.exp.op == TOK.blit) ? (cast(AssignExp)i.exp).e2 : i.exp;
882 1
            if (tb.ty == Tsarray && e.implicitConvTo(tb.nextOf()))
883
            {
884 1
                TypeSArray tsa = cast(TypeSArray)tb;
885 1
                size_t d = cast(size_t)tsa.dim.toInteger();
886 1
                auto elements = new Expressions(d);
887 1
                for (size_t j = 0; j < d; j++)
888 1
                    (*elements)[j] = e;
889 1
                auto ae = new ArrayLiteralExp(e.loc, itype, elements);
890 1
                return ae;
891
            }
892
        }
893 1
        return i.exp;
894
    }
895

896

897 1
    final switch (init.kind)
898
    {
899 1
        case InitKind.void_:   return visitVoid  (cast(  VoidInitializer)init);
900 1
        case InitKind.error:   return visitError (cast( ErrorInitializer)init);
901 1
        case InitKind.struct_: return visitStruct(cast(StructInitializer)init);
902 1
        case InitKind.array:   return visitArray (cast( ArrayInitializer)init);
903 1
        case InitKind.exp:     return visitExp   (cast(   ExpInitializer)init);
904
    }
905
}

Read our documentation on viewing source code .

Loading