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